--- /dev/null
+build-*
\ No newline at end of file
--- /dev/null
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, 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 library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ 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 Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, 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 or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the 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 a program 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.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ 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, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 6. As an exception to the Sections above, you may also compile 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) 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.
+
+ c) 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.
+
+ d) 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 source code 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.
+\f
+ 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 to
+this License.
+\f
+ 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 Library 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.
+\f
+ 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
+\f
+ Appendix: 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 Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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!
--- /dev/null
+Required packages
+-----------------
+
+Before installing c2lib, you need to make sure you have the following
+packages installed:
+
+cdoc http://www.annexia.org/freeware/cdoc/
+make+ http://www.annexia.org/freeware/makeplus/
+pcre http://www.pcre.org/
+
+Building and installing
+-----------------------
+
+./configure [--prefix=/usr --sysconfdir=/etc]
+make+
+make+ test
+make+ install
+
+See the make+ documentation for additional targets (eg. building RPMs).
+
+Problems
+--------
+
+If the build fails, please examine the following files for clues:
+
+build-*/config.h
+build-*/config.mk
+build-*/config.log
+
+If you discover a bug, please contact the package author.
--- /dev/null
+# -*- Makefile -*-
+#
+# This is a make+ file. Make+ is a set of scripts which enhance GNU
+# make and let you build RPMs, and other package types with just one
+# control file. To build this package you will need to download make+
+# from this site: http://www.annexia.org/freeware/makeplus/
+
+PACKAGE := c2lib
+VERSION_MAJOR := 1
+VERSION_MINOR := 4.2
+VERSION := $(VERSION_MAJOR).$(VERSION_MINOR)
+
+SUMMARY := A library of useful functions for C.
+COPYRIGHT := GNU LGPL (see http://www.gnu.org/)
+AUTHOR := Richard Jones <rich@annexia.org>
+
+define DESCRIPTION
+c2lib is a library of useful functions which augment those found in
+the standard libc. It contains a pool allocator, many string
+functions, STL-like vector and hash types and miscellaneous utilities.
+endef
+
+RPM_REQUIRES := pcre >= 3.9
+RPM_GROUP := Development/Libraries
+
+CFLAGS += -Wall -Werror -g -O2 -D_GNU_SOURCE
+ifneq ($(shell uname), SunOS)
+# Avoid a warning about reordering system include paths.
+CFLAGS += $(shell pcre-config --cflags)
+endif
+LIBS += $(shell pcre-config --libs) -lm
+
+OBJS := hash.o matvec.o pool.o pre.o pstring.o tree.o vector.o
+LOBJS := $(OBJS:.o=.lo)
+HEADERS := $(srcdir)/hash.h $(srcdir)/matvec.h \
+ $(srcdir)/pool.h $(srcdir)/pre.h $(srcdir)/pstring.h \
+ $(srcdir)/tree.h $(srcdir)/vector.h
+
+all: static dynamic manpages syms
+
+# Configure the system.
+
+configure:
+ $(MP_CONFIGURE_START)
+ $(MP_REQUIRE_PROG) pcre-config
+ $(MP_CHECK_HEADERS) alloca.h assert.h ctype.h fcntl.h string.h unistd.h
+ $(MP_CHECK_FUNCS) vasprintf
+ $(MP_CONFIGURE_END)
+
+# Build the static library.
+
+static: libc2lib.a
+
+libc2lib.a: $(OBJS)
+ $(MP_LINK_STATIC) $@ $^
+
+# Build the dynamic library.
+
+dynamic: libc2lib.so
+
+libc2lib.so: $(LOBJS)
+ $(MP_LINK_DYNAMIC) $@ $^ $(LIBS)
+
+# Build the manual pages.
+
+manpages: $(srcdir)/*.h
+ if cdoc; then \
+ rm -f *.3; \
+ cdoc \
+ --author '$(AUTHOR)' \
+ --license '$(COPYRIGHT)' \
+ --version '$(PACKAGE)-$(VERSION)' \
+ $^; \
+ fi
+
+# Build the symbols table.
+
+syms: libc2lib.syms
+
+libc2lib.syms: libc2lib.so
+ nm $< | sort | grep -i '^[0-9a-f]' | awk '{print $$1 " " $$3}' > $@
+
+# Test.
+
+test: test_hash test_matvec test_pool test_pre test_pstring test_sash \
+ test_shash test_tree test_vector
+ LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(MP_RUN_TESTS) $^
+
+test_hash: test_hash.o
+ $(CC) $(CFLAGS) $^ -o $@ -L. -lc2lib $(LIBS)
+test_matvec: test_matvec.o
+ $(CC) $(CFLAGS) $^ -o $@ -L. -lc2lib $(LIBS)
+test_pool: test_pool.o
+ $(CC) $(CFLAGS) $^ -o $@ $(LIBS)
+test_pre: test_pre.o
+ $(CC) $(CFLAGS) $^ -o $@ -L. -lc2lib $(LIBS)
+test_pstring: test_pstring.o
+ $(CC) $(CFLAGS) $^ -o $@ -L. -lc2lib $(LIBS)
+test_sash: test_sash.o
+ $(CC) $(CFLAGS) $^ -o $@ -L. -lc2lib $(LIBS)
+test_shash: test_shash.o
+ $(CC) $(CFLAGS) $^ -o $@ -L. -lc2lib $(LIBS)
+test_tree: test_tree.o
+ $(CC) $(CFLAGS) $^ -o $@ -L. -lc2lib $(LIBS)
+test_vector: test_vector.o
+ $(CC) $(CFLAGS) $^ -o $@ -L. -lc2lib $(LIBS)
+
+# Install.
+
+install:
+ install -d $(DESTDIR)$(libdir)
+ install -d $(DESTDIR)$(pkgincludedir)
+ install -d $(DESTDIR)$(man3dir)
+ install -d $(DESTDIR)$(datadir)/rws/symtabs/
+
+ $(MP_INSTALL_STATIC_LIB) libc2lib.a
+ $(MP_INSTALL_DYNAMIC_LIB) libc2lib.so
+ install -m 0644 $(HEADERS) $(DESTDIR)$(pkgincludedir)
+ install -m 0644 *.3 $(DESTDIR)$(man3dir)
+ install -m 0644 *.syms $(DESTDIR)$(datadir)/rws/symtabs/
+
+force:
+
+define WEBSITE
+<% include page_header.msp %>
+
+ <h1>c2lib - a Perl/STL-like library of basics for C</h1>
+
+ <p>
+ c2lib is a library of basic tools for use by C
+ programmers. It contains features heavily influenced
+ by both Perl's string handling and C++'s Standard
+ Template Library (STL). The library has been designed
+ to be very easy to use and is fully documented in
+ manual pages.
+ </p>
+
+ <p>
+ <a href="doc/">There is extensive documentation and
+ a tutorial here.</a>
+ </p>
+
+ <h1>Download</h1>
+
+ <table border="1">
+ <tr>
+ <th> File </th>
+ <th> Format </th>
+ <th> Contents </th>
+ </tr>
+ <tr>
+ <td> <a href="$(PACKAGE)-$(VERSION).tar.gz">$(PACKAGE)-$(VERSION).tar.gz</a> </td>
+ <td> tar.gz </td>
+ <td> Latest source distribution </td>
+ </tr>
+ <tr>
+ <td> <a href="$(PACKAGE)-$(VERSION)-1.i686.rpm">$(PACKAGE)-$(VERSION)-1.i686.rpm</a> </td>
+ <td> i686 binary RPM </td>
+ <td> Binary development libraries, header files, man pages
+ for Red Hat Linux </td>
+ </tr>
+ <tr>
+ <td> <a href="$(PACKAGE)-$(VERSION)-1.src.rpm">$(PACKAGE)-$(VERSION)-1.src.rpm</a> </td>
+ <td> source RPM </td>
+ <td> Source files for Red Hat Linux </td>
+ </tr>
+ </table>
+
+ <p>
+ Dependencies:
+ </p>
+
+ <ul>
+ <li> You will need to install the <a href="http://www.pcre.org/">Perl
+ Compatible Regular Expressions (PCRE)</a> library.
+ <li> Since 1.3.0, c2lib requires the <a href="../makeplus/">make+</a>
+ build system.
+ <li> To rebuild the manual pages which come with the
+ package, you will also need to download
+ <a href="../cdoc/">cdoc</a>.
+ </ul>
+
+ <p>
+ <a href="/cgi-bin/autopatch.pl?dir=c2lib">Patches between versions
+ ...</a>
+ </p>
+
+ <h1>News</h1>
+
+<p>
+<b>Sat Mar 1 2003:</b>
+Created README and INSTALL files (thanks to David Chappell). Updated
+<code>Makefile+</code> to work with the new version of make+.
+<strong>NB: The RPMs were built on Debian and may not work on Red Hat
+Linux.</strong> </p>
+
+<p>
+<b>Sat Feb 8 17:00:47 GMT 2003:</b>
+Ported to Solaris, OpenBSD and FreeBSD (thanks to
+<a href="http://www.azazel.net/">Jeremy Sowden</a>
+and <a href="http://www.mondaymorning.org/">Richard Baker</a>
+for help and equipment). Don't link c2lib itself into the
+<code>test_pool</code> program. Link test programs correctly
+with <code>pcre</code>.
+</p>
+
+<p>
+<strong>Attn:</strong> Solaris
+has a library called <code>libc2</code>. I have had to rename this
+library to <code>libc2lib</code>, so you will need to link your
+programs against <code>-lc2lib</code>. I have also moved the
+header files into the <code>c2lib/<code> subdirectory of
+includedir, so you may need to specify <code>-I/usr/include/c2lib</code>
+when building.
+</p>
+
+<p>
+<b>Sat Dec 7 17:18:02 GMT 2002:</b> Updated to use the
+<a href="../makeplus/">make+</a> build system.
+</p>
+
+<p>
+<b>Mon Nov 25 09:31:37 GMT 2002:</b> Added symbols file for full
+symbol resolution in monolith.
+</p>
+
+ <p>
+ <b>Sun Nov 17 23:31:32 GMT 2002:</b> Debian packages. Added MSP files.
+ <code>pmalloc</code> now initialises memory to <code>0xefefefef</code>
+ so we can catch uninitialised memory problems. Further fixes
+ to compile on RH 7.3. Added <code>vector_push_back_vector</code> etc.
+ </p>
+
+ <p>
+ <b>Tue Oct 15 23:40:42 BST 2002:</b> Multiple bug fixes.
+ </p>
+
+ <p>
+ <b>Sun Oct 13 12:55:08 BST 2002:</b> Added <code>pmap</code>
+ and <code>pgrep</code> functions.
+ </p>
+
+ <p>
+ <b>Tue Oct 8 16:18:02 BST 2002:</b> Fix issues with building on
+ Red Hat Linux 7.3 (thanks to Adam Monsen). The supplied
+ RPM should now install on Red Hat Linux systems.
+ </p>
+
+ <p>
+ <b>Sun Oct 6 18:07:39 BST 2002:</b> Completely rewrote
+ the <code>pstr*split</code> functions so they produce the
+ same results as the Perl equivalents in all the corner
+ cases. Added <code>pstr*split2</code> functions (see
+ the manual pages).
+ </p>
+
+ <p>
+ <b>Sun Oct 6 13:00:39 BST 2002:</b> Added a <code>tree</code>
+ type (required by monolith). Removed the old <code>pmatch*</code> and
+ <code>psubst*</code> functions. These were badly thought
+ out and implemented. Replaced with <code>precomp</code>,
+ <code>prematch</code>, <code>presubst</code> functions
+ which are wrappers around the <a href="http://www.pcre.org/">Perl
+ Compatible Regular Expressions (PCRE)</a> library.
+ <code>pstrresplit</code> has also changed to use PCRE.
+ </p>
+
+ <p>
+ <b>Sat Sep 7 15:24:32 BST 2002:</b> Packages are
+ now available as i686 binary RPMs and source RPMs.
+ </p>
+
+ <h1>Old news and old versions</h1>
+
+ <p>
+ <b>Fri May 2 19:49:25 BST 2002</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.14.tar.gz">c2lib-1.2.14.tar.gz</a> released.
+ Added an extensive tutorial and online manual pages.
+ </p>
+
+ <p>
+ <b>Thu Jun 21 23:12:26 BST 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.12.tar.gz">c2lib-1.2.12.tar.gz</a> released.
+ Fixed <code>psort</code> function and updated documentation.
+ </p>
+
+ <p>
+ <b>Fri Jun 15 15:40:35 BST 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.11.tar.gz">c2lib-1.2.11.tar.gz</a> released.
+ Profiling support. Added <code>pstrncat</code>,
+ <code>psubst</code> and <code>psubstx</code> functions.
+ Fixed a memory leak and did rigorous memory leak
+ checking -- I\'m pretty sure there are none left now.
+ Removed arbitrary limit on number of substring
+ matches in <code>pmatch</code> function.
+ Documentation updates.
+ </p>
+
+ <p>
+ <b>Mon Apr 9 17:18:38 BST 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.8.tar.gz">c2lib-1.2.8.tar.gz</a> released.
+ Documentation fixes.
+ </p>
+
+ <p>
+ <b>Wed Mar 28 14:25:42 BST 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.7.tar.gz">c2lib-1.2.7.tar.gz</a> released.
+ Fixed a problem with calling <code>isspace</code> on
+ Solaris (thanks to Tomonori Manome again).
+ </p>
+
+ <p>
+ <b>Mon Mar 26 12:59:15 BST 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.6.tar.gz">c2lib-1.2.6.tar.gz</a> released.
+ <code>pstrresplit</code> fixed.
+ <code>pvector</code> and <code>pvectora</code> functions
+ added: use these to quickly build vectors from lists of strings.
+ <code>ptrimfront</code>, <code>ptrimback</code> and <code>ptrim</code>
+ functions added for trimming whitespace from strings.
+ <code>pgetline*</code> and <code>pmatch*</code> functions
+ added which make it trivial to read in configuration files.
+ <code>new_subvector</code> added for creating sub-vectors
+ of existing vectors.
+ Some minor const-correctness changes.
+ Documentation updates.
+ Test suite updates.
+ </p>
+
+ <p>
+ <b>Mon Mar 19 11:40:34 GMT 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.3.tar.gz">c2lib-1.2.3.tar.gz</a> released.
+ This adds the <i>shash</i> type: a mapping of strings
+ to anything (another specialized hash).
+ Port to Solaris/Intel and Solaris/Sparc (thanks to
+ Tomonori Manome for this).
+ </p>
+
+ <p>
+ <b>Mon Mar 12 12:12:49 GMT 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.1.tar.gz">c2lib-1.2.1.tar.gz</a> released.
+ This fixes a bug in the way the library was calling
+ <code>pstrcat</code>. Upgrading is highly recommended.
+ </p>
+
+ <p>
+ <b>Fri Mar 9 17:26:45 GMT 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.2.0.tar.gz">c2lib-1.2.0.tar.gz</a> released.
+ The pool allocator has been completely rewritten for this
+ release, and is much more efficient.
+ </p>
+
+ <p>
+ <b>Wed Mar 7 14:56:43 GMT 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.1.12.tar.gz">c2lib-1.1.12.tar.gz</a> released.
+ Added <code>pchrs</code> and <code>pstrs</code> string
+ functions. Added <code>pvsprintf</code>. Changed
+ <code>psprintf</code> to make it much more memory efficient
+ (it uses <code>vasprintf(3)</code> if available).
+ Const-correctness fixes.
+ </p>
+
+ <p>
+ <b>Fri Feb 16 17:46:41 GMT 2001</b>
+ </p>
+
+ <p>
+ <a href="c2lib-1.1.10.tar.gz">c2lib-1.1.10.tar.gz</a> released.
+ All functions are documented in manual pages.
+ </p>
+
+<% include page_footer.msp %>
+endef
+
+upload_website:
+ scp $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE)-$(VERSION)-1.*.rpm \
+ $(PACKAGE)-$(VERSION).bin.tar.gz \
+ 10.0.0.248:annexia.org/freeware/$(PACKAGE)/
+ scp index.html \
+ 10.0.0.248:annexia.org/freeware/$(PACKAGE)/index.msp
+
+.PHONY: static dynamic manpages syms
--- /dev/null
+This is c2lib from http://www.annexia.org/freeware/c2lib/
+
+c2lib is a library of basic tools for use by C programmers. It contains
+features heavily influenced by both Perl's string handling and C++'s
+Standard Template Library (STL). The library has been designed to be very
+easy to use and is fully documented in manual pages.
--- /dev/null
+Ported to Solaris 9 by RWMJ on 2003/02/02.
\ No newline at end of file
--- /dev/null
+#!/bin/sh -
+#
+# This is make+. Make+ is a set of scripts which enhance GNU make and
+# let you build RPMs, and other packages types with just one control
+# file. Read more at http://www.annexia.org/freeware/makeplus/
+#
+# The original author is Richard W.M. Jones <rich@annexia.org>.
+#
+# This software has been explicitly placed in the PUBLIC DOMAIN. You
+# do not need any sort of license or agreement to use or copy this
+# software. You may also copyright this software yourself, and/or
+# relicense it under any terms you want, at any time and at no cost.
+# This allows you (among other things) to include this software with
+# other packages so that the user does not need to download and
+# install make+ separately.
+
+mp_options=""
+
+usage ()
+{
+ cat <<EOF
+./configure [--options]
+
+Installation directory options:
+ --prefix=PREFIX Installation prefix [default: /usr/local]
+ --sysconfdir=SYSCONF Installation prefix for configuration files
+ [default: PREFIX/etc]
+ --localstatedir=STATE Installation prefix for writable files
+ [default: PREFIX/var]
+
+Help options:
+ --help Display this help and exit.
+ --print-mp-cmd Display the make+ command and exit (use as final arg)
+EOF
+ exit 1
+}
+
+while [ $# -gt 0 ]; do
+ opt=$1 ; shift
+
+ case "$opt" in
+ --help)
+ usage
+ ;;
+ --print-mp-cmd)
+ echo "rm -f build-\*/config.mk"
+ echo "make+ $mp_options configure"
+ exit 0
+ ;;
+ --*prefix|--*dir)
+ opt=`echo $opt | sed 's/^--//'`
+ arg=$1 ; shift
+ mp_options="$mp_options $opt=$arg"
+ ;;
+ --*prefix=*|--*dir=*)
+ opt=`echo $opt | sed 's/^--//'`
+ mp_options="$mp_options $opt"
+ ;;
+ *)
+ mp_options="$mp_options $opt"
+ ;;
+ esac
+done
+
+rm -f build-*/config.mk
+make+ $mp_options configure
--- /dev/null
+ROFF = groff -man -Thtml -U
+
+all:
+ @echo "Try the following target: man_pages"
+
+man_pages:
+ ln -s . man3
+ cp ../*.3 .
+ for f in *.3; echo $$f; do $(ROFF) $$f > $$f.html; done
+ rm *.3 man3
+ @echo "Now you need to import the HTML files into index.html"
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>collision_moving_sphere_and_face</title>
+</head>
+<body>
+
+<h1 align=center>collision_moving_sphere_and_face</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#RETURNS">RETURNS</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:38 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+collision_moving_sphere_and_face - detect collision between a moving sphere and a fixed face</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+int collision_moving_sphere_and_face (const float *p0, const float *p1, float radius, const float *points, int nr_points, const float *plane, float *collision_point);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+This function detects collisions between a sphere which is
+moving at constant speed along a linear path and a fixed
+bounded convex polygon ("face").</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The centre of the sphere moves from point <b>p0</b> to point
+<b>p1</b>. The sphere has radius <b>radius</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The face is described by the list of bounding points, and
+the plane coefficients of the plane of the face (you may
+pass <b>plane</b> as <b>NULL</b> in which case the function
+works out the plane coefficients for you, although this is
+generally less efficient).</td></table>
+<a name="RETURNS"></a>
+<h2>RETURNS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+If there was a collision, this function returns true and
+sets the collision point in <b>collision_point</b>. Note
+that the collision point is the position of the centre of
+the sphere at the point of collision, NOT the place where
+the sphere touches the face. If there was no collision, this
+function returns false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>copy_hash</title>
+</head>
+<body>
+
+<h1 align=center>copy_hash</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:40 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+copy_hash - copy a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+hash copy_hash (pool, hash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Copy a hash into a new pool. This function copies the keys
+and values, but if keys and values are pointers, then it
+does not perform a 'deep' copy.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>copy_sash</title>
+</head>
+<body>
+
+<h1 align=center>copy_sash</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:41 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+copy_sash - copy a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+sash copy_sash (pool, sash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Copy a sash into a new pool. This function copies the keys
+and values, but if keys and values are pointers, then it
+does not perform a 'deep' copy.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>copy_shash</title>
+</head>
+<body>
+
+<h1 align=center>copy_shash</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:42 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+copy_shash - copy a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+shash copy_shash (pool, shash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Copy a shash into a new pool. This function copies the keys
+and values, but if keys and values are pointers, then it
+does not perform a 'deep' copy.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>copy_vector</title>
+</head>
+<body>
+
+<h1 align=center>copy_vector</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:43 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+copy_vector, new_subvector - copy a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+vector copy_vector (pool, vector v);
+vector new_subvector (pool, vector v, int i, int j);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Copy a vector <b>v</b> into pool <b>pool</b>. If the vector
+contains pointers, then this function will not copy the
+pointed-to data as well: you will need to copy this yourself
+if appropriate.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_subvector</b> creates a copy of part of an existing
+vector. The new vector contains the <b>j-i</b> elements of
+the old vector starting at element number <b>i</b> and
+finishing at element number <b>j-1</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>delete_pool</title>
+</head>
+<body>
+
+<h1 align=center>delete_pool</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:44 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+delete_pool - delete a pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void delete_pool (pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Delete a pool or subpool. This also deletes any subpools
+that the pool may own (and recursively subpools of those
+subpools, etc.)</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+#include <pool.h>
+#include <pstring.h>
+
+const char *strings[] = { "John", "Paul", "George", "Ringo" };
+
+main ()
+{
+ pool pool = global_pool;
+ vector v = pvectora (pool, strings, 4);
+ printf ("Introducing the Beatles: %s\n", pjoin (pool, v, ", "));
+}
--- /dev/null
+#include <stdio.h>
+#include <hash.h>
+#include <pstring.h>
+
+main ()
+{
+ pool pool = global_pool;
+ sash h = new_sash (pool);
+ char *fruit;
+ const char *color;
+
+ sash_insert (h, "banana", "yellow");
+ sash_insert (h, "orange", "orange");
+ sash_insert (h, "apple", "red");
+ sash_insert (h, "kiwi", "green");
+ sash_insert (h, "grapefruit", "yellow");
+ sash_insert (h, "pear", "green");
+ sash_insert (h, "tomato", "red");
+ sash_insert (h, "tangerine", "orange");
+
+ for (;;)
+ {
+ printf ("Please type in the name of a fruit: ");
+ fruit = pgetline (pool, stdin, 0);
+
+ if (sash_get (h, fruit, color))
+ printf ("The color of that fruit is %s.\n", color);
+ else
+ printf ("Sorry, I don't know anything about that fruit.\n");
+ }
+}
--- /dev/null
+#include <assert.h>
+#include <pstring.h>
+
+char *given_name = "Richard";
+char *family_name = "Jones";
+char *email_address = "rich@annexia.org";
+
+main ()
+{
+ pool pool = global_pool;
+ char *email, *s;
+ vector v;
+
+ email =
+ psprintf (pool, "%s %s <%s>", given_name, family_name, email_address);
+
+ printf ("full email address is: %s\n", email);
+
+ v = pstrcsplit (pool, email, ' ');
+
+ printf ("split email into %d components\n", vector_size (v));
+
+ vector_get (v, 0, s);
+ printf ("first component is: %s\n", s);
+ assert (strcmp (s, given_name) == 0);
+
+ vector_get (v, 1, s);
+ printf ("second component is: %s\n", s);
+ assert (strcmp (s, family_name) == 0);
+
+ vector_get (v, 2, s);
+ printf ("third component is: %s\n", s);
+ s = pstrdup (pool, s);
+ s++;
+ s[strlen(s)-1] = '\0';
+ assert (strcmp (s, email_address) == 0);
+}
--- /dev/null
+#include <pool.h>
+#include <vector.h>
+#include <pstring.h>
+
+main ()
+{
+ pool pool = global_pool;
+ vector v = new_vector (pool, int);
+ int i, prod = 1;
+
+ for (i = 1; i <= 10; ++i)
+ vector_push_back (v, i);
+
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ int elem;
+
+ vector_get (v, i, elem);
+ prod *= elem;
+ }
+
+ printf ("product of integers: %s = %d\n",
+ pjoin (pool, pvitostr (pool, v), " * "),
+ prod);
+}
--- /dev/null
+#include <pool.h>
+#include <vector.h>
+#include <pstring.h>
+
+main ()
+{
+ pool pool = global_pool;
+ vector v = pvector (pool,
+ "a", "b", "c", "d", "e",
+ "f", "g", "h", "i", "j", 0);
+ const char *X = "X";
+
+ printf ("Original vector contains: %s\n",
+ pjoin (pool, v, ", "));
+
+ vector_erase_range (v, 3, 6);
+
+ printf ("After erasing elements 3-5, vector contains: %s\n",
+ pjoin (pool, v, ", "));
+
+ vector_insert (v, 3, X);
+ vector_insert (v, 4, X);
+ vector_insert (v, 5, X);
+
+ printf ("After inserting 3 Xs, vector contains: %s\n",
+ pjoin (pool, v, ", "));
+
+ vector_clear (v);
+ vector_fill (v, X, 10);
+
+ printf ("After clearing and inserting 10 Xs, vector contains: %s\n",
+ pjoin (pool, v, ", "));
+}
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>plane_translate_along_normal</title>
+</head>
+<body>
+
+<h1 align=center>plane_translate_along_normal</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:45 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+plane_translate_along_normal, face_translate_along_normal - translate a plane or face some distance in the direction of the normal</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+void plane_translate_along_normal (const float *plane, float distance, float *new_plane);
+void face_translate_along_normal (const float *points, int nr_points, const float *plane, float distance, float *new_points, float *new_plane);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Given an existing <b>plane</b> (expressed as plane
+coefficients), produce a new plane <b>new_plane</b> which
+has been translated by <b>distance</b> units along the
+direction of the normal. The new plane is also returned as
+plane coefficients.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>face_translate_along_normal</b> is similar, except that
+it also translates a list of points by the same
+distance.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>plane_coefficients(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>global_pool</title>
+</head>
+<body>
+
+<h1 align=center>global_pool</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:46 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+global_pool - the global pool for global allocations</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+pool global_pool;
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+This is the global pool which is allocated before
+<b>main()</b> is called and deleted automatically upon
+program exit. Items allocated on this pool cannot be deleted
+until the program ends, and so it is a good idea not to
+allocate short-lived items here.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_erase</title>
+</head>
+<body>
+
+<h1 align=center>hash_erase</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:47 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_erase, _hash_erase - erase a key from a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define hash_erase(h,key) _hash_erase((h),&(key))
+int _hash_erase (hash, const void *key);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Erase <b>key</b> from the hash. If an element was erased,
+this returns true, else this returns false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_get</title>
+</head>
+<body>
+
+<h1 align=center>hash_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:48 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_get, _hash_get, hash_get_ptr, _hash_get_ptr, hash_exists - look up in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define hash_get(h,key,value) _hash_get ((h), &(key), &(value))
+int _hash_get (hash, const void *key, void *value);
+#define hash_get_ptr(h,key,ptr) _hash_get_ptr ((h), &(key), &(ptr))
+int _hash_get_ptr (hash, const void *key, void **ptr);
+#define hash_exists(h,key) _hash_get_ptr ((h), &(key), 0)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Get the <b>value</b> associated with key <b>key</b> and
+return true. If there is no <b>value</b> associated with
+<b>key</b>, this returns false and <b>value</b> is left
+unchanged.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_ptr</b> variants return a pointer rather than
+copying out the entire value object. The pointer is
+typically only valid for a short period of time.
+Particularly if you insert or remove elements from the hash,
+this pointer may become invalid.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>hash_exists</b> simply tests whether or not <b>key</b>
+exists in the hash. If so, it returns true, otherwise
+false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_get</title>
+</head>
+<body>
+
+<h1 align=center>hash_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:49 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_get, _hash_get, hash_get_ptr, _hash_get_ptr, hash_exists - look up in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define hash_get(h,key,value) _hash_get ((h), &(key), &(value))
+int _hash_get (hash, const void *key, void *value);
+#define hash_get_ptr(h,key,ptr) _hash_get_ptr ((h), &(key), &(ptr))
+int _hash_get_ptr (hash, const void *key, void **ptr);
+#define hash_exists(h,key) _hash_get_ptr ((h), &(key), 0)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Get the <b>value</b> associated with key <b>key</b> and
+return true. If there is no <b>value</b> associated with
+<b>key</b>, this returns false and <b>value</b> is left
+unchanged.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_ptr</b> variants return a pointer rather than
+copying out the entire value object. The pointer is
+typically only valid for a short period of time.
+Particularly if you insert or remove elements from the hash,
+this pointer may become invalid.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>hash_exists</b> simply tests whether or not <b>key</b>
+exists in the hash. If so, it returns true, otherwise
+false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_get_buckets_used</title>
+</head>
+<body>
+
+<h1 align=center>hash_get_buckets_used</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:50 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_get_buckets_used, hash_get_buckets_allocated - return the number of buckets in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int hash_get_buckets_used (hash);
+int hash_get_buckets_allocated (hash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the number of hash buckets used and allocated. The
+number of buckets allocated is always a power of 2. See also
+<b>hash_set_buckets_allocated</b> to change the number used
+in the hash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_get_buckets_used</title>
+</head>
+<body>
+
+<h1 align=center>hash_get_buckets_used</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:51 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_get_buckets_used, hash_get_buckets_allocated - return the number of buckets in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int hash_get_buckets_used (hash);
+int hash_get_buckets_allocated (hash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the number of hash buckets used and allocated. The
+number of buckets allocated is always a power of 2. See also
+<b>hash_set_buckets_allocated</b> to change the number used
+in the hash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_get</title>
+</head>
+<body>
+
+<h1 align=center>hash_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:52 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_get, _hash_get, hash_get_ptr, _hash_get_ptr, hash_exists - look up in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define hash_get(h,key,value) _hash_get ((h), &(key), &(value))
+int _hash_get (hash, const void *key, void *value);
+#define hash_get_ptr(h,key,ptr) _hash_get_ptr ((h), &(key), &(ptr))
+int _hash_get_ptr (hash, const void *key, void **ptr);
+#define hash_exists(h,key) _hash_get_ptr ((h), &(key), 0)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Get the <b>value</b> associated with key <b>key</b> and
+return true. If there is no <b>value</b> associated with
+<b>key</b>, this returns false and <b>value</b> is left
+unchanged.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_ptr</b> variants return a pointer rather than
+copying out the entire value object. The pointer is
+typically only valid for a short period of time.
+Particularly if you insert or remove elements from the hash,
+this pointer may become invalid.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>hash_exists</b> simply tests whether or not <b>key</b>
+exists in the hash. If so, it returns true, otherwise
+false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_insert</title>
+</head>
+<body>
+
+<h1 align=center>hash_insert</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:53 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_insert, _hash_insert - insert a (key, value) pair into a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define hash_insert(h,key,value) _hash_insert((h),&(key),&(value))
+int _hash_insert (hash, const void *key, const void *value);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Insert an element (<b>key</b>, <b>value</b>) into the hash.
+If <b>key</b> already exists in the hash, then the existing
+value is replaced by <b>value</b> and the function returns
+true. If there was no previous <b>key</b> in the hash then
+this function returns false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_keys</title>
+</head>
+<body>
+
+<h1 align=center>hash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:54 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_keys, hash_keys_in_pool, hash_values, hash_values_in_pool - return a vector of the keys or values in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector hash_keys (hash);
+vector hash_keys_in_pool (hash, pool);
+vector hash_values (hash);
+vector hash_values_in_pool (hash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of hash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the hash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_keys</title>
+</head>
+<body>
+
+<h1 align=center>hash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:56 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_keys, hash_keys_in_pool, hash_values, hash_values_in_pool - return a vector of the keys or values in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector hash_keys (hash);
+vector hash_keys_in_pool (hash, pool);
+vector hash_values (hash);
+vector hash_values_in_pool (hash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of hash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the hash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_set_buckets_allocated</title>
+</head>
+<body>
+
+<h1 align=center>hash_set_buckets_allocated</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:57 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_set_buckets_allocated - set the number of buckets</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+void hash_set_buckets_allocated (hash, int);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Set the number of buckets allocated. You may ONLY do this
+when you have just created the hash and before you have
+inserted any elements. Otherwise the results are undefined
+(and probably bad). The number of buckets MUST be a power of
+2.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_size</title>
+</head>
+<body>
+
+<h1 align=center>hash_size</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:58 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_size - return the number of (key, value) pairs in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int hash_size (hash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Count the number of (key, value) pairs in the
+hash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_keys</title>
+</head>
+<body>
+
+<h1 align=center>hash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:56:59 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_keys, hash_keys_in_pool, hash_values, hash_values_in_pool - return a vector of the keys or values in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector hash_keys (hash);
+vector hash_keys_in_pool (hash, pool);
+vector hash_values (hash);
+vector hash_values_in_pool (hash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of hash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the hash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>hash_keys</title>
+</head>
+<body>
+
+<h1 align=center>hash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:00 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+hash_keys, hash_keys_in_pool, hash_values, hash_values_in_pool - return a vector of the keys or values in a hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector hash_keys (hash);
+vector hash_keys_in_pool (hash, pool);
+vector hash_values (hash);
+vector hash_values_in_pool (hash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of hash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the hash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>identity_matrix</title>
+</head>
+<body>
+
+<h1 align=center>identity_matrix</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:01 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+identity_matrix, zero_vec, new_identity_matrix, new_zero_vec, make_identity_matrix, make_zero_vec - identity matrix and zero vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float identity_matrix[16];
+float zero_vec[4];
+float *new_identity_matrix (pool);
+float *new_zero_vec (pool);
+#define make_identity_matrix(m) memcpy (m, identity_matrix, sizeof(float)*16);
+#define make_zero_vec(v) memcpy (v, zero_vec, sizeof (float) * 4);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>identity_matrix</b> variable contains a read-only
+copy of the identity matrix. The <b>zero_vec</b> variable
+contains a read-only copy of the zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>new_identity_matrix</b> to allocate a new identity
+matrix variable in <b>pool</b>. Use <b>new_zero_vec</b> to
+similarly allocate a new zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>make_identity_matrix</b> to copy the identity matrix
+over an existing matrix <b>m</b>. Use <b>make_zero_vec</b>
+to similarly copy the zero vector over an existing vector
+<b>v</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_matrix(3)</b>, <b>new_vec(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>c2lib documentation index</title>
+ <style type="text/css"><!--
+ h1 {
+ text-align: center;
+ }
+ pre {
+ background-color: #eeeeff;
+ }
+ code {
+ color: green;
+ font-weight: bold;
+ }
+ --></style>
+ </head>
+
+ <body bgcolor="#ffffff">
+ <h1>c2lib documentation index</h1>
+
+ <p>
+ <code>c2lib</code> is a library of basic tools for use by C
+ programmers. It contains features heavily influenced by
+ both Perl's string handling and C++'s Standard Template
+ Library (STL).
+ </p>
+
+ <p>
+ The primary aims of <code>c2lib</code> are:
+ </p>
+
+ <ul>
+ <li> Be very simple to use.
+ <li> Provide rich abstract data types (ADTs) for C programmers
+ to use.
+ <li> Provide some of the advantages of Perl with only
+ around a factor of 2-3 code-size expansion over Perl itself.
+ <li> Retain most of the efficiency advantages of C.
+ <li> Remain compatible with existing libc functions (particularly
+ existing string and regular expression functions).
+ <li> Clean, fully documented API.
+ </ul>
+
+ <h2>Tutorial and programming examples</h2>
+
+ <h3>Join a list of strings and print</h3>
+
+<pre>
+ #include <pool.h>
+ #include <pstring.h>
+
+ const char *strings[] = { "John", "Paul", "George", "Ringo" };
+5
+ main ()
+ {
+ pool pool = global_pool;
+ vector v = pvectora (pool, strings, 4);
+10 printf ("Introducing the Beatles: %s\n", pjoin (pool, v, ", "));
+ }
+</pre>
+
+ <p>
+ When run, this program prints:
+ </p>
+
+<pre>
+Introducing the Beatles: John, Paul, George, Ringo
+</pre>
+
+ <p>
+ Compare this to the equivalent Perl code:
+ </p>
+
+<pre>
+#!/usr/bin/perl
+
+printf "Introducing the Beatles: %s\n",
+ join(", ", "John", "Paul", "George", "Ringo");
+</pre>
+
+ <p>
+ The <code>pjoin(3)</code> function on line 10 is
+ equivalent to the plain <code>join</code> function
+ in Perl. It takes a list of strings and joins them
+ with a separator string (in this case <code>", "</code>),
+ and creates a new string which is returned and printed.
+ </p>
+
+ <p>
+ The <code>pvectora(3)</code> function (line 9) takes a normal C
+ array of strings and converts it into a <code>c2lib</code>
+ <code>vector</code>. You will find out more about
+ <code>vector</code>s later.
+ </p>
+
+ <p>
+ In this case all our allocations are done in a standard
+ pool which is created automatically before <code>main</code> is
+ called and deleted after <code>main</code> returns. This pool is
+ called <code>global_pool(3)</code>. You will find out
+ more about <code>pool</code>s below.
+ </p>
+
+ <p>
+ Notice that, as with most <code>c2lib</code> programs, there is
+ no need to explicitly deallocate (free) objects once you
+ have finished using them. Almost all of the time, objects
+ are freed automatically for you by the system.
+ </p>
+
+ <h3>A vector of integers</h3>
+
+<pre>
+ #include <pool.h>
+ #include <vector.h>
+ #include <pstring.h>
+
+5 main ()
+ {
+ pool pool = global_pool;
+ vector v = new_vector (pool, int);
+ int i, prod = 1;
+10
+ for (i = 1; i <= 10; ++i)
+ vector_push_back (v, i);
+
+ for (i = 0; i < vector_size (v); ++i)
+15 {
+ int elem;
+
+ vector_get (v, i, elem);
+ prod *= elem;
+20 }
+
+ printf ("product of integers: %s = %d\n",
+ pjoin (pool, pvitostr (pool, v), " * "),
+ prod);
+25 }
+</pre>
+
+ <p>
+ When run:
+ </p>
+
+<pre>
+product of integers: 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 = 3628800
+</pre>
+
+ <p>
+ The call to <code>new_vector(3)</code> on line 8 creates a new
+ vector object (abstract data type). In this case the vector is
+ allocated in the global pool and you have told it that each
+ element of the vector will be of type <code>int</code>. Vectors
+ are arrays which automatically expand when you push elements
+ onto them. This vector behaves very much like a C++ STL
+ <code>vector<int></code> or a Perl array.
+ </p>
+
+ <p>
+ On lines 11-12, we push the numbers 1 through to 10 into
+ the vector. The <code>vector_push_back(3)</code> function
+ pushes an element onto the end of the vector. There are
+ also <code>vector_pop_back(3)</code> (removes and returns the
+ last element of a vector), <code>vector_push_front(3)</code>
+ and <code>vector_pop_front(3)</code> operations.
+ </p>
+
+ <p>
+ Lines 14-20 show the general pattern for iterating over
+ the elements in a vector. The call to <code>vector_get</code>
+ (line 18) returns the <code>i</code>th element of vector <code>v</code>
+ into variable <code>elem</code>.
+ </p>
+
+ <p>
+ Finally lines 22-24 print out the result. We use the
+ <code>pjoin(3)</code> function again to join the numbers
+ with the string <code>" * "</code> between each pair.
+ Also note the use of the strange <code>pvitostr(3)</code>
+ function. <code>pjoin(3)</code> is expecting a vector
+ of strings (ie. a vector of <code>char *</code>), but
+ we have a vector of <code>int</code>, which is
+ incompatible. The <code>pvitostr(3)</code> function
+ promotes a vector of integers into a vector of strings.
+ </p>
+
+ <p>
+ The <code>c2lib</code> library stores vectors as arrays and
+ reallocates them using <code>prealloc(3)</code> whenever it
+ needs to expand them. This means that certain operations on
+ vectors are efficient, and some other operations are less
+ efficient. Getting an element of a vector or replacing an
+ element in the middle of a vector are both fast O(1) operations,
+ equivalent to the ordinary C index ([]) operator.
+ <code>vector_push_back(3)</code> and
+ <code>vector_pop_back(3)</code> are also fast. However
+ <code>vector_push_front(3)</code> and
+ <code>vector_pop_front(3)</code> are O(n) operations because
+ they require the library to shift up all the elements in the
+ array by one place. Normally however if your vectors are very
+ short (say, fewer than 100 elements), the speed difference will
+ not be noticable, whereas the productivity gains from using
+ vectors over hand-rolled linked lists or other structures will
+ be large. The <code>vector</code> type also allows you
+ to insert and remove elements in the middle of the array,
+ as shown in the next example below:
+ </p>
+
+<pre>
+ #include <pool.h>
+ #include <vector.h>
+ #include <pstring.h>
+
+5 main ()
+ {
+ pool pool = global_pool;
+ vector v = pvector (pool,
+ "a", "b", "c", "d", "e",
+10 "f", "g", "h", "i", "j", 0);
+ const char *X = "X";
+
+ printf ("Original vector contains: %s\n",
+ pjoin (pool, v, ", "));
+15
+ vector_erase_range (v, 3, 6);
+
+ printf ("After erasing elements 3-5, vector contains: %s\n",
+ pjoin (pool, v, ", "));
+20
+ vector_insert (v, 3, X);
+ vector_insert (v, 4, X);
+ vector_insert (v, 5, X);
+
+25 printf ("After inserting 3 Xs, vector contains: %s\n",
+ pjoin (pool, v, ", "));
+
+ vector_clear (v);
+ vector_fill (v, X, 10);
+30
+ printf ("After clearing and inserting 10 Xs, vector contains: %s\n",
+ pjoin (pool, v, ", "));
+ }
+</pre>
+
+ <p>
+ When run:
+ </p>
+
+<pre>
+Original vector contains: a, b, c, d, e, f, g, h, i, j
+After erasing elements 3-5, vector contains: a, b, c, g, h, i, j
+After inserting 3 Xs, vector contains: a, b, c, X, X, X, g, h, i, j
+After clearing and inserting 10 Xs, vector contains: X, X, X, X, X, X, X, X, X, X
+</pre>
+
+ <p>
+ This example demonstrates the following functions:
+ </p>
+
+ <ul>
+ <li> <code>vector_erase_range(3)</code> which is used
+ to erase a range of elements from the middle of
+ a vector.
+ <li> <code>vector_insert(3)</code> which is used to
+ insert single elements into a vector.
+ <li> <code>vector_clear(3)</code> which completely
+ clears the vector - removing all elements.
+ <li> <code>vector_fill(3)</code> which fills a vector
+ with identical elements.
+ </ul>
+
+ <p>
+ For more information, see the respective manual pages.
+ </p>
+
+ <p>
+ You can store just about anything in a vector: strings,
+ pointers, wide integers, complex structures, etc. If you do
+ want to directly store large objects in a vector, you must
+ remember that the vector type actually copies those objects into
+ and out of the vector each time you insert, push, get, pop and
+ so on. For some large structures, you may want to store a
+ pointer instead (in fact with strings you have no choice: you
+ are always storing a pointer in the vector itself).
+ </p>
+
+ <h3>Strings are just <code>char *</code></h3>
+
+ <p>
+ <code>c2lib</code> doesn't have a fancy string type.
+ Instead we just use plain old <code>char *</code>. This
+ is possible because pools (see below) mean that we don't
+ need to worry about when to copy or deallocate specific
+ objects.
+ </p>
+
+ <p>
+ The great benefit of using plain <code>char *</code>
+ for strings is that we can continue to use the
+ familiar libc functions such as <code>strcmp(3)</code>,
+ <code>strcpy(3)</code>, <code>strlen(3)</code>, <code>printf(3)</code>
+ and so on, as in the next example.
+ </p>
+
+<pre>
+ #include <assert.h>
+ #include <pstring.h>
+
+ char *given_name = "Richard";
+5 char *family_name = "Jones";
+ char *email_address = "rich@annexia.org";
+
+ main ()
+ {
+10 pool pool = global_pool;
+ char *email, *s;
+ vector v;
+
+ email =
+15 psprintf (pool, "%s %s <%s>", given_name, family_name, email_address);
+
+ printf ("full email address is: %s\n", email);
+
+ v = pstrcsplit (pool, email, ' ');
+20
+ printf ("split email into %d components\n", vector_size (v));
+
+ vector_get (v, 0, s);
+ printf ("first component is: %s\n", s);
+25 assert (strcmp (s, given_name) == 0);
+
+ vector_get (v, 1, s);
+ printf ("second component is: %s\n", s);
+ assert (strcmp (s, family_name) == 0);
+30
+ vector_get (v, 2, s);
+ printf ("third component is: %s\n", s);
+ s = pstrdup (pool, s);
+ s++;
+35 s[strlen(s)-1] = '\0';
+ assert (strcmp (s, email_address) == 0);
+ }
+</pre>
+
+ <p>
+ When run:
+ </p>
+
+<pre>
+full email address is: Richard Jones <rich@annexia.org>
+split email into 3 components
+first component is: Richard
+second component is: Jones
+third component is: <rich@annexia.org>
+</pre>
+
+ <p>
+ Line 15 demonstrates the <code>psprintf(3)</code> function
+ which is like the ordinary <code>sprintf(3)</code>,
+ but is (a) safe, and (b) allocates the string in the
+ pool provided, ensuring that it will be safely deallocated
+ later.
+ </p>
+
+ <p>
+ The <code>pstrcsplit(3)</code> function is similar to the
+ Perl <code>split</code>. It takes a string and splits it
+ into a vector of strings, in this case on the space
+ character. There are also other functions for splitting
+ on a string or on a regular expression.
+ </p>
+
+ <p>
+ The final part of the code, lines 21-36, prints out
+ the components of the split string. The <code>vector_get(3)</code>
+ function is used to pull the strings out of the vector object.
+ </p>
+
+ <p>
+ Notice on line 33 that before we remove the beginning
+ and end < ... > from around the email address,
+ we first duplicate the string using <code>pstrdup(3)</code>.
+ In this case it is not strictly necessary to duplicate
+ the string <code>s</code> because we know that
+ <code>pstrcsplit(3)</code> actually allocates new
+ copies of the strings in the vector which it returns.
+ However in general this is good practice because
+ otherwise we would be modifying the contents of the
+ original vector <code>v</code>.
+ </p>
+
+ <h3>Hashes</h3>
+
+ <p>
+ Hashes give you all the power of Perl's "%" hashes. In
+ fact the way they work is very similar (but more powerful:
+ unlike Perl's hashes the key does not need to be a string).
+ </p>
+
+ <p>
+ In <code>c2lib</code> there are three flavors of hash.
+ However they all work in essentially the same way, and
+ all have exactly the same functionality. The reason for
+ having the three flavors is just to work around an obscure
+ problem with the ANSI C specification!
+ </p>
+
+ <p>
+ The three flavors are:
+ </p>
+
+ <table>
+ <tr>
+ <th> hash </th>
+ <td> A hash of any non-string type to any non-string type. </td>
+ </tr>
+ <tr>
+ <th> sash </th>
+ <td> A hash of <code>char *</code> to <code>char *</code>. </td>
+ </tr>
+ <tr>
+ <th> shash </th>
+ <td> A hash of <code>char *</code> to any non-string type. </td>
+ </tr>
+ </table>
+
+ <p>
+ As with vectors, the phrase "any non-string type" can
+ be simple integers or chars, pointers, or complex large
+ structures if you wish.
+ </p>
+
+ <p>
+ Here is a short program showing you how to use a
+ sash (but note that the same functions are available
+ for all of the other flavors):
+ </p>
+
+<pre>
+ #include <stdio.h>
+ #include <hash.h>
+ #include <pstring.h>
+
+5 main ()
+ {
+ pool pool = global_pool;
+ sash h = new_sash (pool);
+ char *fruit;
+10 const char *color;
+
+ sash_insert (h, "banana", "yellow");
+ sash_insert (h, "orange", "orange");
+ sash_insert (h, "apple", "red");
+15 sash_insert (h, "kiwi", "green");
+ sash_insert (h, "grapefruit", "yellow");
+ sash_insert (h, "pear", "green");
+ sash_insert (h, "tomato", "red");
+ sash_insert (h, "tangerine", "orange");
+20
+ for (;;)
+ {
+ printf ("Please type in the name of a fruit: ");
+ fruit = pgetline (pool, stdin, 0);
+25
+ if (sash_get (h, fruit, color))
+ printf ("The color of that fruit is %s.\n", color);
+ else
+ printf ("Sorry, I don't know anything about that fruit.\n");
+30 }
+ }
+</pre>
+
+ <p>
+ When run:
+ </p>
+
+<pre>
+Please type in the name of a fruit: <b>orange</b>
+The color of that fruit is orange.
+Please type in the name of a fruit: <b>apple</b>
+The color of that fruit is red.
+Please type in the name of a fruit: <b>dragon fruit</b>
+Sorry, I don't know anything about that fruit.
+</pre>
+
+ <p>
+ The sash is allocated on line 8 using the <code>new_sash(3)</code>
+ function.
+ </p>
+
+ <p>
+ We populate the sash using the simple <code>sash_insert(3)</code>
+ functions (lines 12-19).
+ </p>
+
+ <p>
+ The <code>sash_get(3)</code> function retrieves a value
+ (<code>color</code>) from
+ the sash using the key given (<code>fruit</code>). It
+ returns true if a value was found, or false if there
+ was no matching key.
+ </p>
+
+ <p>
+ There are many potentially powerful functions available
+ for manipulating hashes, sashes and shashes (below,
+ <code>*</code> stands for either "h", "s" or "sh"):
+ </p>
+
+ <ul>
+ <li> <code>*ash_exists(3)</code> tells you if a key
+ exists. It is equivalent to the Perl <code>exists</code>
+ function.
+ <li> <code>*ash_erase(3)</code> removes a key. It
+ is equivalent to the Perl <code>delete</code> function.
+ <li> <code>*ash_keys(3)</code> returns all of the
+ keys of a hash in a vector. It is equivalent to the
+ Perl <code>keys</code> function.
+ <li> <code>*ash_values(3)</code> returns all of the
+ values of a hash in a vector. It is equivalent to the
+ Perl <code>values</code> function.
+ <li> <code>*ash_size(3)</code> counts the number of keys.
+ </ul>
+
+ <h3>Advanced used of pools</h3>
+
+ <p>
+ So far we have only touched upon pools, and it may not
+ be clear in the examples above why they don't in fact
+ leak memory. There appears to be no deallocation being
+ done, which is quite counter-intuitive to most C programmers!
+ </p>
+
+ <p>
+ Pools are collections of related objects (where an
+ "object" is some sort of memory allocation).
+ </p>
+
+ <p>
+ In C you are normally responsible for allocating and
+ deallocating every single object, like so:
+ </p>
+
+<pre>
+p = malloc (size);
+
+/* ... use p ... */
+
+free (p);
+</pre>
+
+ <p>
+ However in <code>c2lib</code> we first allocate a pool,
+ then use <code>pmalloc(3)</code> and <code>prealloc(3)</code>
+ to allocate lots of related objects in the pool.
+ At the end of the program, all of the objects can be
+ deleted in one go just by calling <code>delete_pool(3)</code>.
+ </p>
+
+ <p>
+ There is one special pool, called <code>global_pool(3)</code>.
+ This pool is created for you before <code>main</code> is
+ called, and it is deleted for you after <code>main</code>
+ returns (or if <code>exit(3)</code> is called). You don't
+ ever need to worry about deallocating <code>global_pool(3)</code>
+ (in fact, if you try to, your program might core dump).
+ </p>
+
+ <p>
+ Thus most short programs like the ones above should just
+ allocate all objects in <code>global_pool(3)</code>, and
+ never need to worry about deallocating the objects or
+ the pool.
+ </p>
+
+ <p>
+ For larger programs, and programs that are expected to run for a
+ long time like servers, you will need to learn about pools.
+ </p>
+
+ <p>
+ Pools are organised in a hierarchy. This means that you often
+ allocate one pool <i>inside</i> another pool. Here is a
+ common pattern:
+ </p>
+
+<pre>
+main ()
+{
+ /* ... use global_pool for allocations here ... */
+
+ for (;;) /* for each request: */
+ {
+ pool pool = new_subpool (global_pool);
+
+ /* ... process the request using pool ... */
+
+ delete_pool (pool);
+ }
+}
+</pre>
+
+ <p>
+ <code>pool</code> is created as a subpool of
+ <code>global_pool(3)</code> for the duration of
+ the request. At the end of the request the pool
+ (and therefore all objects inside it) is deallocated.
+ </p>
+
+ <p>
+ The advantage of creating <code>pool</code> as a
+ subpool of <code>global_pool(3)</code> is that if
+ the request processing code calls <code>exit(3)</code>
+ in the middle of the request, then <code>global_pool(3)</code>
+ will be deallocated in the normal way and as a consequence
+ of this <code>pool</code> will also be properly deallocated.
+ </p>
+
+ <p>
+ You can also use <code>new_pool(3)</code> to create a
+ completely new top-level pool. There are some rare
+ circumstances when you will need to do this, but
+ generally you should avoid creating pools which are
+ not subpools. If in doubt, always create subpools of
+ <code>global_pool(3)</code> or of the pool immediately
+ "above" you.
+ </p>
+
+ <p>
+ Pools don't just store memory allocations. You can attach
+ other types of objects to pools, or trigger functions which
+ are run when the pool is deallocated. <code>pool_register_fd(3)</code>
+ attaches a file descriptor to a pool, meaning that the file
+ descriptor is closed when the pool is deleted (note
+ however that there is no way to unattach a file descriptor
+ from a pool, so don't go and call <code>close(3)</code>
+ on the file descriptor once you've attached it to
+ a pool. <code>pool_register_cleanup_fn(3)</code>
+ registers your own clean-up function which is called
+ when the pool is deleted. Although you should
+ normally use <code>pmalloc(3)</code> and/or
+ <code>prealloc(3)</code> to allocate objects directly
+ in pools, you can also allocate them normally using
+ <code>malloc(3)</code> and attach them to the pool
+ using <code>pool_register_malloc(3)</code>. The object
+ will be freed up automatically when the pool is
+ deallocated.
+ </p>
+
+ <p>
+ Pools become very important when writing multi-threaded
+ servers using the <code>pthrlib</code> library. Each
+ thread processes a single request or command. A pool
+ is created for every thread, and is automatically
+ deleted when the thread exits. This assumes of course
+ that threads (and hence requests) are short-lived, which
+ is a reasonable assumption for most HTTP-like services.
+ </p>
+
+ <h2>Links to manual pages</h2>
+
+ <p>
+ (These manual pages are not always up to date. For the
+ latest documentation, always consult the manual pages
+ supplied with the latest <code>c2lib</code> package!)
+ </p>
+
+ <h3>Pools</h3>
+
+ <ul>
+ <li> <a href="delete_pool.3.html"><code>delete_pool(3)</code></a> </li>
+ <li> <a href="global_pool.3.html"><code>global_pool(3)</code></a> </li>
+ <li> <a href="new_pool.3.html"><code>new_pool(3)</code></a> </li>
+ <li> <a href="new_subpool.3.html"><code>new_subpool(3)</code></a> </li>
+ <li> <a href="pcalloc.3.html"><code>pcalloc(3)</code></a> </li>
+ <li> <a href="pmalloc.3.html"><code>pmalloc(3)</code></a> </li>
+ <li> <a href="pool_get_stats.3.html"><code>pool_get_stats(3)</code></a> </li>
+ <li> <a href="pool_register_cleanup_fn.3.html"><code>pool_register_cleanup_fn(3)</code></a> </li>
+ <li> <a href="pool_register_fd.3.html"><code>pool_register_fd(3)</code></a> </li>
+ <li> <a href="pool_register_malloc.3.html"><code>pool_register_malloc(3)</code></a> </li>
+ <li> <a href="pool_set_bad_malloc_handler.3.html"><code>pool_set_bad_malloc_handler(3)</code></a> </li>
+ <li> <a href="prealloc.3.html"><code>prealloc(3)</code></a> </li>
+ </ul>
+
+ <h3>Vectors</h3>
+
+ <ul>
+ <li> <a href="copy_vector.3.html"><code>copy_vector(3)</code></a> </li>
+ <li> <a href="new_vector.3.html"><code>new_vector(3)</code></a> </li>
+ <li> <a href="vector_allocated.3.html"><code>vector_allocated(3)</code></a> </li>
+ <li> <a href="vector_clear.3.html"><code>vector_clear(3)</code></a> </li>
+ <li> <a href="vector_compare.3.html"><code>vector_compare(3)</code></a> </li>
+ <li> <a href="vector_element_size.3.html"><code>vector_element_size(3)</code></a> </li>
+ <li> <a href="vector_erase.3.html"><code>vector_erase(3)</code></a> </li>
+ <li> <a href="vector_erase_range.3.html"><code>vector_erase_range(3)</code></a> </li>
+ <li> <a href="vector_fill.3.html"><code>vector_fill(3)</code></a> </li>
+ <li> <a href="vector_get.3.html"><code>vector_get(3)</code></a> </li>
+ <li> <a href="vector_get_ptr.3.html"><code>vector_get_ptr(3)</code></a> </li>
+ <li> <a href="vector_grep.3.html"><code>vector_grep(3)</code></a> </li>
+ <li> <a href="vector_grep_pool.3.html"><code>vector_grep_pool(3)</code></a> </li>
+ <li> <a href="vector_insert.3.html"><code>vector_insert(3)</code></a> </li>
+ <li> <a href="vector_insert_array.3.html"><code>vector_insert_array(3)</code></a> </li>
+ <li> <a href="vector_map.3.html"><code>vector_map(3)</code></a> </li>
+ <li> <a href="vector_map_pool.3.html"><code>vector_map_pool(3)</code></a> </li>
+ <li> <a href="vector_pop_back.3.html"><code>vector_pop_back(3)</code></a> </li>
+ <li> <a href="vector_pop_front.3.html"><code>vector_pop_front(3)</code></a> </li>
+ <li> <a href="vector_push_back.3.html"><code>vector_push_back(3)</code></a> </li>
+ <li> <a href="vector_push_front.3.html"><code>vector_push_front(3)</code></a> </li>
+ <li> <a href="vector_reallocate.3.html"><code>vector_reallocate(3)</code></a> </li>
+ <li> <a href="vector_replace.3.html"><code>vector_replace(3)</code></a> </li>
+ <li> <a href="vector_replace_array.3.html"><code>vector_replace_array(3)</code></a> </li>
+ <li> <a href="vector_reverse.3.html"><code>vector_reverse(3)</code></a> </li>
+ <li> <a href="vector_size.3.html"><code>vector_size(3)</code></a> </li>
+ <li> <a href="vector_sort.3.html"><code>vector_sort(3)</code></a> </li>
+ <li> <a href="vector_swap.3.html"><code>vector_swap(3)</code></a> </li>
+ </ul>
+
+ <h3>Hashes</h3>
+
+ <ul>
+ <li> <a href="copy_hash.3.html"><code>copy_hash(3)</code></a> </li>
+ <li> <a href="copy_sash.3.html"><code>copy_sash(3)</code></a> </li>
+ <li> <a href="copy_shash.3.html"><code>copy_shash(3)</code></a> </li>
+ <li> <a href="hash_erase.3.html"><code>hash_erase(3)</code></a> </li>
+ <li> <a href="hash_exists.3.html"><code>hash_exists(3)</code></a> </li>
+ <li> <a href="hash_get.3.html"><code>hash_get(3)</code></a> </li>
+ <li> <a href="hash_get_buckets_allocated.3.html"><code>hash_get_buckets_allocated(3)</code></a> </li>
+ <li> <a href="hash_get_buckets_used.3.html"><code>hash_get_buckets_used(3)</code></a> </li>
+ <li> <a href="hash_get_ptr.3.html"><code>hash_get_ptr(3)</code></a> </li>
+ <li> <a href="hash_insert.3.html"><code>hash_insert(3)</code></a> </li>
+ <li> <a href="hash_keys.3.html"><code>hash_keys(3)</code></a> </li>
+ <li> <a href="hash_keys_in_pool.3.html"><code>hash_keys_in_pool(3)</code></a> </li>
+ <li> <a href="hash_set_buckets_allocated.3.html"><code>hash_set_buckets_allocated(3)</code></a> </li>
+ <li> <a href="hash_size.3.html"><code>hash_size(3)</code></a> </li>
+ <li> <a href="hash_values.3.html"><code>hash_values(3)</code></a> </li>
+ <li> <a href="hash_values_in_pool.3.html"><code>hash_values_in_pool(3)</code></a> </li>
+ <li> <a href="new_hash.3.html"><code>new_hash(3)</code></a> </li>
+ <li> <a href="new_sash.3.html"><code>new_sash(3)</code></a> </li>
+ <li> <a href="new_shash.3.html"><code>new_shash(3)</code></a> </li>
+ <li> <a href="sash_erase.3.html"><code>sash_erase(3)</code></a> </li>
+ <li> <a href="sash_exists.3.html"><code>sash_exists(3)</code></a> </li>
+ <li> <a href="sash_get.3.html"><code>sash_get(3)</code></a> </li>
+ <li> <a href="sash_get_buckets_allocated.3.html"><code>sash_get_buckets_allocated(3)</code></a> </li>
+ <li> <a href="sash_get_buckets_used.3.html"><code>sash_get_buckets_used(3)</code></a> </li>
+ <li> <a href="sash_insert.3.html"><code>sash_insert(3)</code></a> </li>
+ <li> <a href="sash_keys.3.html"><code>sash_keys(3)</code></a> </li>
+ <li> <a href="sash_keys_in_pool.3.html"><code>sash_keys_in_pool(3)</code></a> </li>
+ <li> <a href="sash_set_buckets_allocated.3.html"><code>sash_set_buckets_allocated(3)</code></a> </li>
+ <li> <a href="sash_size.3.html"><code>sash_size(3)</code></a> </li>
+ <li> <a href="sash_values.3.html"><code>sash_values(3)</code></a> </li>
+ <li> <a href="sash_values_in_pool.3.html"><code>sash_values_in_pool(3)</code></a> </li>
+ <li> <a href="shash_erase.3.html"><code>shash_erase(3)</code></a> </li>
+ <li> <a href="shash_exists.3.html"><code>shash_exists(3)</code></a> </li>
+ <li> <a href="shash_get.3.html"><code>shash_get(3)</code></a> </li>
+ <li> <a href="shash_get_buckets_allocated.3.html"><code>shash_get_buckets_allocated(3)</code></a> </li>
+ <li> <a href="shash_get_buckets_used.3.html"><code>shash_get_buckets_used(3)</code></a> </li>
+ <li> <a href="shash_get_ptr.3.html"><code>shash_get_ptr(3)</code></a> </li>
+ <li> <a href="shash_insert.3.html"><code>shash_insert(3)</code></a> </li>
+ <li> <a href="shash_keys.3.html"><code>shash_keys(3)</code></a> </li>
+ <li> <a href="shash_keys_in_pool.3.html"><code>shash_keys_in_pool(3)</code></a> </li>
+ <li> <a href="shash_set_buckets_allocated.3.html"><code>shash_set_buckets_allocated(3)</code></a> </li>
+ <li> <a href="shash_size.3.html"><code>shash_size(3)</code></a> </li>
+ <li> <a href="shash_values.3.html"><code>shash_values(3)</code></a> </li>
+ <li> <a href="shash_values_in_pool.3.html"><code>shash_values_in_pool(3)</code></a> </li>
+ </ul>
+
+ <h3>Strings and miscellaneous</h3>
+
+ <ul>
+ <li> <a href="pchomp.3.html"><code>pchomp(3)</code></a> </li>
+ <li> <a href="pchrs.3.html"><code>pchrs(3)</code></a> </li>
+ <li> <a href="pconcat.3.html"><code>pconcat(3)</code></a> </li>
+ <li> <a href="pdtoa.3.html"><code>pdtoa(3)</code></a> </li>
+ <li> <a href="pgetline.3.html"><code>pgetline(3)</code></a> </li>
+ <li> <a href="pgetlinec.3.html"><code>pgetlinec(3)</code></a> </li>
+ <li> <a href="pgetlinex.3.html"><code>pgetlinex(3)</code></a> </li>
+ <li> <a href="pitoa.3.html"><code>pitoa(3)</code></a> </li>
+ <li> <a href="pjoin.3.html"><code>pjoin(3)</code></a> </li>
+ <li> <a href="pmatch.3.html"><code>pmatch(3)</code></a> </li>
+ <li> <a href="pmatchx.3.html"><code>pmatchx(3)</code></a> </li>
+ <li> <a href="pmemdup.3.html"><code>pmemdup(3)</code></a> </li>
+ <li> <a href="psort.3.html"><code>psort(3)</code></a> </li>
+ <li> <a href="psprintf.3.html"><code>psprintf(3)</code></a> </li>
+ <li> <a href="pstrcat.3.html"><code>pstrcat(3)</code></a> </li>
+ <li> <a href="pstrcsplit.3.html"><code>pstrcsplit(3)</code></a> </li>
+ <li> <a href="pstrdup.3.html"><code>pstrdup(3)</code></a> </li>
+ <li> <a href="pstrlwr.3.html"><code>pstrlwr(3)</code></a> </li>
+ <li> <a href="pstrncat.3.html"><code>pstrncat(3)</code></a> </li>
+ <li> <a href="pstrndup.3.html"><code>pstrndup(3)</code></a> </li>
+ <li> <a href="pstrresplit.3.html"><code>pstrresplit(3)</code></a> </li>
+ <li> <a href="pstrs.3.html"><code>pstrs(3)</code></a> </li>
+ <li> <a href="pstrsplit.3.html"><code>pstrsplit(3)</code></a> </li>
+ <li> <a href="pstrupr.3.html"><code>pstrupr(3)</code></a> </li>
+ <li> <a href="psubst.3.html"><code>psubst(3)</code></a> </li>
+ <li> <a href="psubstr.3.html"><code>psubstr(3)</code></a> </li>
+ <li> <a href="psubstx.3.html"><code>psubstx(3)</code></a> </li>
+ <li> <a href="ptrim.3.html"><code>ptrim(3)</code></a> </li>
+ <li> <a href="ptrimback.3.html"><code>ptrimback(3)</code></a> </li>
+ <li> <a href="ptrimfront.3.html"><code>ptrimfront(3)</code></a> </li>
+ <li> <a href="pvdtostr.3.html"><code>pvdtostr(3)</code></a> </li>
+ <li> <a href="pvector.3.html"><code>pvector(3)</code></a> </li>
+ <li> <a href="pvectora.3.html"><code>pvectora(3)</code></a> </li>
+ <li> <a href="pvitostr.3.html"><code>pvitostr(3)</code></a> </li>
+ <li> <a href="pvsprintf.3.html"><code>pvsprintf(3)</code></a> </li>
+ <li> <a href="pvxtostr.3.html"><code>pvxtostr(3)</code></a> </li>
+ <li> <a href="pxtoa.3.html"><code>pxtoa(3)</code></a> </li>
+ </ul>
+
+ <h3>Matrix and vector math</h3>
+
+ <ul>
+ <li> <a href="collision_moving_sphere_and_face.3.html"><code>collision_moving_sphere_and_face(3)</code></a> </li>
+
+ <li> <a href="face_translate_along_normal.3.html"><code>face_translate_along_normal(3)</code></a> </li>
+ <li> <a href="identity_matrix.3.html"><code>identity_matrix(3)</code></a> </li>
+ <li> <a href="make_identity_matrix.3.html"><code>make_identity_matrix(3)</code></a> </li>
+ <li> <a href="make_zero_vec.3.html"><code>make_zero_vec(3)</code></a> </li>
+ <li> <a href="new_identity_matrix.3.html"><code>new_identity_matrix(3)</code></a> </li>
+ <li> <a href="new_matrix.3.html"><code>new_matrix(3)</code></a> </li>
+ <li> <a href="new_subvector.3.html"><code>new_subvector(3)</code></a> </li>
+ <li> <a href="new_vec.3.html"><code>new_vec(3)</code></a> </li>
+
+ <li> <a href="new_zero_vec.3.html"><code>new_zero_vec(3)</code></a> </li>
+ <li> <a href="plane_coefficients.3.html"><code>plane_coefficients(3)</code></a> </li>
+ <li> <a href="plane_translate_along_normal.3.html"><code>plane_translate_along_normal(3)</code></a> </li>
+
+ <li> <a href="point_distance_to_face.3.html"><code>point_distance_to_face(3)</code></a> </li>
+ <li> <a href="point_distance_to_line.3.html"><code>point_distance_to_line(3)</code></a> </li>
+ <li> <a href="point_distance_to_line_segment.3.html"><code>point_distance_to_line_segment(3)</code></a> </li>
+ <li> <a href="point_distance_to_plane.3.html"><code>point_distance_to_plane(3)</code></a> </li>
+ <li> <a href="point_face_angle_sum.3.html"><code>point_face_angle_sum(3)</code></a> </li>
+ <li> <a href="point_is_inside_plane.3.html"><code>point_is_inside_plane(3)</code></a> </li>
+ <li> <a href="point_lies_in_face.3.html"><code>point_lies_in_face(3)</code></a> </li>
+ <li> <a href="vec_angle_between.3.html"><code>vec_angle_between(3)</code></a> </li>
+ <li> <a href="vec_dot_product.3.html"><code>vec_dot_product(3)</code></a> </li>
+ <li> <a href="vec_magnitude2d.3.html"><code>vec_magnitude2d(3)</code></a> </li>
+ <li> <a href="vec_magnitude.3.html"><code>vec_magnitude(3)</code></a> </li>
+ <li> <a href="vec_magnitude_in_direction.3.html"><code>vec_magnitude_in_direction(3)</code></a> </li>
+ <li> <a href="vec_normalize2d.3.html"><code>vec_normalize2d(3)</code></a> </li>
+ <li> <a href="vec_normalize.3.html"><code>vec_normalize(3)</code></a> </li>
+ <li> <a href="zero_vec.3.html"><code>zero_vec(3)</code></a> </li>
+ </ul>
+
+ <hr>
+ <address><a href="mailto:rich@annexia.org">Richard Jones</a></address>
+<!-- Created: Wed May 1 19:36:16 BST 2002 -->
+<!-- hhmts start -->
+Last modified: Fri May 2 19:42:09 BST 2002
+<!-- hhmts end -->
+ </body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>identity_matrix</title>
+</head>
+<body>
+
+<h1 align=center>identity_matrix</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:02 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+identity_matrix, zero_vec, new_identity_matrix, new_zero_vec, make_identity_matrix, make_zero_vec - identity matrix and zero vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float identity_matrix[16];
+float zero_vec[4];
+float *new_identity_matrix (pool);
+float *new_zero_vec (pool);
+#define make_identity_matrix(m) memcpy (m, identity_matrix, sizeof(float)*16);
+#define make_zero_vec(v) memcpy (v, zero_vec, sizeof (float) * 4);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>identity_matrix</b> variable contains a read-only
+copy of the identity matrix. The <b>zero_vec</b> variable
+contains a read-only copy of the zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>new_identity_matrix</b> to allocate a new identity
+matrix variable in <b>pool</b>. Use <b>new_zero_vec</b> to
+similarly allocate a new zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>make_identity_matrix</b> to copy the identity matrix
+over an existing matrix <b>m</b>. Use <b>make_zero_vec</b>
+to similarly copy the zero vector over an existing vector
+<b>v</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_matrix(3)</b>, <b>new_vec(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>identity_matrix</title>
+</head>
+<body>
+
+<h1 align=center>identity_matrix</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:03 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+identity_matrix, zero_vec, new_identity_matrix, new_zero_vec, make_identity_matrix, make_zero_vec - identity matrix and zero vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float identity_matrix[16];
+float zero_vec[4];
+float *new_identity_matrix (pool);
+float *new_zero_vec (pool);
+#define make_identity_matrix(m) memcpy (m, identity_matrix, sizeof(float)*16);
+#define make_zero_vec(v) memcpy (v, zero_vec, sizeof (float) * 4);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>identity_matrix</b> variable contains a read-only
+copy of the identity matrix. The <b>zero_vec</b> variable
+contains a read-only copy of the zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>new_identity_matrix</b> to allocate a new identity
+matrix variable in <b>pool</b>. Use <b>new_zero_vec</b> to
+similarly allocate a new zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>make_identity_matrix</b> to copy the identity matrix
+over an existing matrix <b>m</b>. Use <b>make_zero_vec</b>
+to similarly copy the zero vector over an existing vector
+<b>v</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_matrix(3)</b>, <b>new_vec(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>new_hash</title>
+</head>
+<body>
+
+<h1 align=center>new_hash</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:04 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+new_hash, _hash_new - allocate a new hash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define new_hash(pool,key_type,value_type) _hash_new ((pool), sizeof (key_type), sizeof (value_type))
+hash _hash_new (pool, size_t key_size, size_t value_size);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate a new hash in <b>pool</b> mapping <b>key_type</b>
+to <b>value_type</b>. You can map both simple types like
+<b>int</b> and also aggregate types like structures and
+unions. However, beware of aggregate types that might
+contain 'holes' because of alignment -- such types will
+probably not work as you expect, particularly if used as
+keys.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+If you wish to have a hash which maps strings to something,
+then calling <b>new_hash(pool, char *, char *)</b> (for
+example) will not do what you expect. You are better to use
+either a sash (string to string hash) or a shash (string to
+anything hash) instead (see <b>new_sash(3)</b> and
+<b>new_shash(3)</b>).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>identity_matrix</title>
+</head>
+<body>
+
+<h1 align=center>identity_matrix</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:06 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+identity_matrix, zero_vec, new_identity_matrix, new_zero_vec, make_identity_matrix, make_zero_vec - identity matrix and zero vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float identity_matrix[16];
+float zero_vec[4];
+float *new_identity_matrix (pool);
+float *new_zero_vec (pool);
+#define make_identity_matrix(m) memcpy (m, identity_matrix, sizeof(float)*16);
+#define make_zero_vec(v) memcpy (v, zero_vec, sizeof (float) * 4);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>identity_matrix</b> variable contains a read-only
+copy of the identity matrix. The <b>zero_vec</b> variable
+contains a read-only copy of the zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>new_identity_matrix</b> to allocate a new identity
+matrix variable in <b>pool</b>. Use <b>new_zero_vec</b> to
+similarly allocate a new zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>make_identity_matrix</b> to copy the identity matrix
+over an existing matrix <b>m</b>. Use <b>make_zero_vec</b>
+to similarly copy the zero vector over an existing vector
+<b>v</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_matrix(3)</b>, <b>new_vec(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>new_matrix</title>
+</head>
+<body>
+
+<h1 align=center>new_matrix</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:07 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+new_matrix, new_vec - allocate a new matrix or vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+#define new_matrix(pool) ((float *) pmalloc ((pool), sizeof (float) * 16))
+#define new_vec(pool) ((float *) pmalloc ((pool), sizeof (float) * 4))
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_matrix</b> allocates a new 4x4 matrix of floats in
+<b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_vec</b> allocates a new 4-vector of floats in
+<b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+You may use these functions to allocate matrices and vectors
+dynamically, or you may allocate them statically. The other
+matrix and vector functions available do not distriguish
+between dynamically and statically allocated
+variables.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Note: All matrices are stored in COLUMN-MAJOR ORDER! This is
+for compatibility with OpenGL, but it is the OPPOSITE of the
+natural C row-major ordering, so beware.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_identity_matrix(3)</b>,
+<b>new_zero_vec(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>new_pool</title>
+</head>
+<body>
+
+<h1 align=center>new_pool</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:08 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+new_pool - allocate a new pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+pool new_pool (void);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate a new pool. Pools must eventually be deleted
+explicitly by calling <b>delete_pool(3)</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Note that <b>new_pool</b> is now deprecated. It is almost
+always better to create a subpool of the global pool,
+ie:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pool = new_subpool (global_pool);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+This has the distinct advantage that your new pool will be
+cleaned up properly if the process calls
+<b>exit</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_subpool(3)</b>, <b>global_pool(3)</b>,
+<b>delete_pool(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>new_sash</title>
+</head>
+<body>
+
+<h1 align=center>new_sash</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:09 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+new_sash - allocate a new sash (string hash)</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+sash new_sash (pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate a new sash in <b>pool</b> mapping strings to
+strings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use a string hash in preference to a hash of <b>char *</b>
+-> <b>char *</b> which will probably not quite work as
+you expect.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>new_shash</title>
+</head>
+<body>
+
+<h1 align=center>new_shash</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:10 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+new_shash - allocate a new shash (string -> something hash)</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define new_shash(pool,value_type) _shash_new ((pool), sizeof (value_type))
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate a new shash in <b>pool</b> mapping strings to
+strings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use a shash in preference to a hash of <b>char *</b> ->
+something which will probably not quite work as you
+expect.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>new_subpool</title>
+</head>
+<body>
+
+<h1 align=center>new_subpool</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:11 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+new_subpool - allocate a subpool of an existing pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+pool new_subpool (pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate a new subpool. The pool may either be deleted
+explicitly, or else is deleted implicitly when the parent
+pool is deleted.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>copy_vector</title>
+</head>
+<body>
+
+<h1 align=center>copy_vector</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:12 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+copy_vector, new_subvector - copy a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+vector copy_vector (pool, vector v);
+vector new_subvector (pool, vector v, int i, int j);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Copy a vector <b>v</b> into pool <b>pool</b>. If the vector
+contains pointers, then this function will not copy the
+pointed-to data as well: you will need to copy this yourself
+if appropriate.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_subvector</b> creates a copy of part of an existing
+vector. The new vector contains the <b>j-i</b> elements of
+the old vector starting at element number <b>i</b> and
+finishing at element number <b>j-1</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>new_matrix</title>
+</head>
+<body>
+
+<h1 align=center>new_matrix</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:13 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+new_matrix, new_vec - allocate a new matrix or vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+#define new_matrix(pool) ((float *) pmalloc ((pool), sizeof (float) * 16))
+#define new_vec(pool) ((float *) pmalloc ((pool), sizeof (float) * 4))
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_matrix</b> allocates a new 4x4 matrix of floats in
+<b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_vec</b> allocates a new 4-vector of floats in
+<b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+You may use these functions to allocate matrices and vectors
+dynamically, or you may allocate them statically. The other
+matrix and vector functions available do not distriguish
+between dynamically and statically allocated
+variables.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Note: All matrices are stored in COLUMN-MAJOR ORDER! This is
+for compatibility with OpenGL, but it is the OPPOSITE of the
+natural C row-major ordering, so beware.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_identity_matrix(3)</b>,
+<b>new_zero_vec(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>new_vector</title>
+</head>
+<body>
+
+<h1 align=center>new_vector</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:14 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+new_vector, _vector_new - allocate a new vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define new_vector(pool,type) _vector_new ((pool), sizeof (type))
+vector _vector_new (pool, size_t size);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate a new vector in <b>pool</b> of type <b>type</b>.
+The first form is just a macro which evaluates the size of
+<b>type</b>. The second form creates a vector with elements
+of the given <b>size</b> directly.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>identity_matrix</title>
+</head>
+<body>
+
+<h1 align=center>identity_matrix</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:15 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+identity_matrix, zero_vec, new_identity_matrix, new_zero_vec, make_identity_matrix, make_zero_vec - identity matrix and zero vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float identity_matrix[16];
+float zero_vec[4];
+float *new_identity_matrix (pool);
+float *new_zero_vec (pool);
+#define make_identity_matrix(m) memcpy (m, identity_matrix, sizeof(float)*16);
+#define make_zero_vec(v) memcpy (v, zero_vec, sizeof (float) * 4);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>identity_matrix</b> variable contains a read-only
+copy of the identity matrix. The <b>zero_vec</b> variable
+contains a read-only copy of the zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>new_identity_matrix</b> to allocate a new identity
+matrix variable in <b>pool</b>. Use <b>new_zero_vec</b> to
+similarly allocate a new zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>make_identity_matrix</b> to copy the identity matrix
+over an existing matrix <b>m</b>. Use <b>make_zero_vec</b>
+to similarly copy the zero vector over an existing vector
+<b>v</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_matrix(3)</b>, <b>new_vec(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pmalloc</title>
+</head>
+<body>
+
+<h1 align=center>pmalloc</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#BUGS">BUGS</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:16 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pmalloc, pcalloc, prealloc - allocate memory in a pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void *pmalloc (pool, size_t n);
+void *pcalloc (pool, size_t nmemb, size_t size);
+void *prealloc (pool, void *ptr, size_t n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate memory in a pool or, if pool is null, on the main
+heap (equivalent to plain <b>malloc</b>). If memory is
+allocated in a real pool, then it is automatically freed
+when the pool is deleted.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Memory returned is word-aligned.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+If a memory allocation fails, the <b>bad_malloc_handler</b>
+function is called (which defaults to just calling
+<b>abort(3)</b>).</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pcalloc</b> is identical to <b>pmalloc</b> but also sets
+the memory to zero before returning it.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>prealloc</b> increases the size of an existing memory
+allocation. <b>prealloc</b> might move the memory in the
+process of reallocating it.</td></table>
+<a name="BUGS"></a>
+<h2>BUGS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>prealloc</b> cannot reduce the size of an existing memory
+allocation.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pchomp</title>
+</head>
+<body>
+
+<h1 align=center>pchomp</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:17 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pchomp - remove line endings from a string</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pchomp (char *line);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Remove line endings (either CR, CRLF or LF) from the string
+argument. The string is modified in-place and a pointer to
+the string is also returned.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pchrs</title>
+</head>
+<body>
+
+<h1 align=center>pchrs</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:18 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pchrs, pstrs - generate a string of n repeated characters or strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pchrs (pool, char c, int n);
+char *pstrs (pool, const char *str, int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pchrs (pool, 'c', n)</b> is similar to the Perl
+expression <b>'c' x n</b>. It generates a pool-allocated
+string of <b>n</b> copies of character
+<b>'c'</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrs (pool, str, n)</b> is similar to the Perl
+expression <b>str x n</b>. It generates a pool-allocated
+string of <b>n</b> copies of the string
+<b>str</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pconcat</title>
+</head>
+<body>
+
+<h1 align=center>pconcat</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:19 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pconcat, pjoin - concatenate a vector of strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pconcat (pool, vector);
+char *pjoin (pool, vector, const char *sep);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pconcat</b> concatenates a vector of strings to form a
+string.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pjoin</b> is similar except that <b>sep</b> is inserted
+between each concatenated string in the output.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pjoin</b> is kind of the opposite of
+<b>pstrsplit(3)</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pitoa</title>
+</head>
+<body>
+
+<h1 align=center>pitoa</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:21 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pitoa, pdtoa, pxtoa - convert number types to strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pitoa (pool, int);
+char *pdtoa (pool, double);
+char *pxtoa (pool, unsigned);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+These functions convert a decimal <b>int</b>, <b>double</b>
+or hexadecimal <b>unsigned</b> into a string, which is
+allocated in <b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pitoa</b> is equivalent to <b>psprintf (pool,
+"%d", i)</b>, and the other functions have similar
+equivalents.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pgetline</title>
+</head>
+<body>
+
+<h1 align=center>pgetline</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:22 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pgetline, pgetlinex, pgetlinec - read a line from a file, optionally removing comments</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pgetline (pool, FILE *fp, char *line);
+char *pgetlinex (pool, FILE *fp, char *line, const char *comment_set, int flags);
+#define pgetlinec(p,fp,line) pgetlinex ((p), (fp), (line),</b> <i>#",</i><b>0)"
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetline</b> reads a single line from a file and returns
+it. It allocates enough space to read lines of arbitrary'
+and '0) are length. Line ending characters (' automatically
+removed from the end of the line.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>pool</b> argument is a pool for allocating the line.
+The <b>fp</b> argument is the C <b>FILE</b> pointer. The
+<b>line</b> argument is a pointer to a string allocated in
+pool which will be reallocated and filled with the contents
+of the line. You may pass <b>line</b> as <b>NULL</b> to get
+a newly allocated buffer.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>pgetline</b> in one of the following two
+ways:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>line = pgetline (pool, fp, line);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+or</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>line = pgetline (pool, fp, NULL);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetlinex</b> is a more advanced function which reads a
+line from a file, optionally removing comments,
+concatenating together lines which have been split with a
+backslash, and ignoring blank lines. <b>pgetlinex</b> (and
+the related macro <b>pgetlinec</b>) are very useful for
+reading lines of input from a configuration
+file.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>pool</b> argument is a pool for allocating the line.
+The <b>fp</b> argument is the C <b>FILE</b> pointer. The
+<b>line</b> argument is a buffer allocated in pool which
+will be reallocated and filled with the result.
+<b>comment_set</b> is the set of possible comment characters
+-- eg. <b>"#!"</b> to allow either <b>#</b> or
+<b>!</b> to be used to introduce comments. <b>flags</b> is
+zero or more of the following flags OR-ed
+together:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PGETL_NO_CONCAT</b>: Don't concatenate lines which have
+been split with trailing backslash characters.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PGETL_INLINE_COMMENTS</b>: Treat everything following a
+comment character as a comment. The default is to only allow
+comments which appear on a line on their own.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetlinec</b> is a helper macro which calls
+<b>pgetlinex</b> with <b>comment_set == "#"</b>
+and <b>flags == 0</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmatch(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pgetline</title>
+</head>
+<body>
+
+<h1 align=center>pgetline</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:23 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pgetline, pgetlinex, pgetlinec - read a line from a file, optionally removing comments</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pgetline (pool, FILE *fp, char *line);
+char *pgetlinex (pool, FILE *fp, char *line, const char *comment_set, int flags);
+#define pgetlinec(p,fp,line) pgetlinex ((p), (fp), (line),</b> <i>#",</i><b>0)"
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetline</b> reads a single line from a file and returns
+it. It allocates enough space to read lines of arbitrary'
+and '0) are length. Line ending characters (' automatically
+removed from the end of the line.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>pool</b> argument is a pool for allocating the line.
+The <b>fp</b> argument is the C <b>FILE</b> pointer. The
+<b>line</b> argument is a pointer to a string allocated in
+pool which will be reallocated and filled with the contents
+of the line. You may pass <b>line</b> as <b>NULL</b> to get
+a newly allocated buffer.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>pgetline</b> in one of the following two
+ways:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>line = pgetline (pool, fp, line);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+or</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>line = pgetline (pool, fp, NULL);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetlinex</b> is a more advanced function which reads a
+line from a file, optionally removing comments,
+concatenating together lines which have been split with a
+backslash, and ignoring blank lines. <b>pgetlinex</b> (and
+the related macro <b>pgetlinec</b>) are very useful for
+reading lines of input from a configuration
+file.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>pool</b> argument is a pool for allocating the line.
+The <b>fp</b> argument is the C <b>FILE</b> pointer. The
+<b>line</b> argument is a buffer allocated in pool which
+will be reallocated and filled with the result.
+<b>comment_set</b> is the set of possible comment characters
+-- eg. <b>"#!"</b> to allow either <b>#</b> or
+<b>!</b> to be used to introduce comments. <b>flags</b> is
+zero or more of the following flags OR-ed
+together:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PGETL_NO_CONCAT</b>: Don't concatenate lines which have
+been split with trailing backslash characters.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PGETL_INLINE_COMMENTS</b>: Treat everything following a
+comment character as a comment. The default is to only allow
+comments which appear on a line on their own.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetlinec</b> is a helper macro which calls
+<b>pgetlinex</b> with <b>comment_set == "#"</b>
+and <b>flags == 0</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmatch(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pgetline</title>
+</head>
+<body>
+
+<h1 align=center>pgetline</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:24 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pgetline, pgetlinex, pgetlinec - read a line from a file, optionally removing comments</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pgetline (pool, FILE *fp, char *line);
+char *pgetlinex (pool, FILE *fp, char *line, const char *comment_set, int flags);
+#define pgetlinec(p,fp,line) pgetlinex ((p), (fp), (line),</b> <i>#",</i><b>0)"
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetline</b> reads a single line from a file and returns
+it. It allocates enough space to read lines of arbitrary'
+and '0) are length. Line ending characters (' automatically
+removed from the end of the line.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>pool</b> argument is a pool for allocating the line.
+The <b>fp</b> argument is the C <b>FILE</b> pointer. The
+<b>line</b> argument is a pointer to a string allocated in
+pool which will be reallocated and filled with the contents
+of the line. You may pass <b>line</b> as <b>NULL</b> to get
+a newly allocated buffer.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>pgetline</b> in one of the following two
+ways:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>line = pgetline (pool, fp, line);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+or</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>line = pgetline (pool, fp, NULL);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetlinex</b> is a more advanced function which reads a
+line from a file, optionally removing comments,
+concatenating together lines which have been split with a
+backslash, and ignoring blank lines. <b>pgetlinex</b> (and
+the related macro <b>pgetlinec</b>) are very useful for
+reading lines of input from a configuration
+file.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>pool</b> argument is a pool for allocating the line.
+The <b>fp</b> argument is the C <b>FILE</b> pointer. The
+<b>line</b> argument is a buffer allocated in pool which
+will be reallocated and filled with the result.
+<b>comment_set</b> is the set of possible comment characters
+-- eg. <b>"#!"</b> to allow either <b>#</b> or
+<b>!</b> to be used to introduce comments. <b>flags</b> is
+zero or more of the following flags OR-ed
+together:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PGETL_NO_CONCAT</b>: Don't concatenate lines which have
+been split with trailing backslash characters.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PGETL_INLINE_COMMENTS</b>: Treat everything following a
+comment character as a comment. The default is to only allow
+comments which appear on a line on their own.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pgetlinec</b> is a helper macro which calls
+<b>pgetlinex</b> with <b>comment_set == "#"</b>
+and <b>flags == 0</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmatch(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pitoa</title>
+</head>
+<body>
+
+<h1 align=center>pitoa</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:25 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pitoa, pdtoa, pxtoa - convert number types to strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pitoa (pool, int);
+char *pdtoa (pool, double);
+char *pxtoa (pool, unsigned);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+These functions convert a decimal <b>int</b>, <b>double</b>
+or hexadecimal <b>unsigned</b> into a string, which is
+allocated in <b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pitoa</b> is equivalent to <b>psprintf (pool,
+"%d", i)</b>, and the other functions have similar
+equivalents.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pconcat</title>
+</head>
+<body>
+
+<h1 align=center>pconcat</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:26 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pconcat, pjoin - concatenate a vector of strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pconcat (pool, vector);
+char *pjoin (pool, vector, const char *sep);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pconcat</b> concatenates a vector of strings to form a
+string.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pjoin</b> is similar except that <b>sep</b> is inserted
+between each concatenated string in the output.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pjoin</b> is kind of the opposite of
+<b>pstrsplit(3)</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>plane_coefficients</title>
+</head>
+<body>
+
+<h1 align=center>plane_coefficients</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:27 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+plane_coefficients - calculate the coefficient form for a plane</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+void plane_coefficients (const float *p, const float *q, const float *r, float *co);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Given three points, not colinear, which naturally form a
+plane, calculate the 4-vector form for the plane
+coefficients. The three points are passed as <b>p</b>,
+<b>q</b> and <b>r</b>. The coefficients are returned in
+vector <b>co</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The four coefficients returned are respectively <b>a</b>,
+<b>b</b>, <b>c</b> and <b>d</b> in the standard plane
+equation:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>a x + b y + c z + d = 0</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+(Note that many texts use <b>- d</b>, so be
+warned).</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The normal (perpendicular) vector to the plane may be
+derived immediately: it is just <b>(a, b, c)</b>. Note that
+the normal vector is not normalized!</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Planes are unbounded: they stretch off to infinity in all
+directions. If what you really want are bounded convex
+polygons, then you need to use a c2lib
+"face".</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>plane_translate_along_normal</title>
+</head>
+<body>
+
+<h1 align=center>plane_translate_along_normal</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:28 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+plane_translate_along_normal, face_translate_along_normal - translate a plane or face some distance in the direction of the normal</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+void plane_translate_along_normal (const float *plane, float distance, float *new_plane);
+void face_translate_along_normal (const float *points, int nr_points, const float *plane, float distance, float *new_points, float *new_plane);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Given an existing <b>plane</b> (expressed as plane
+coefficients), produce a new plane <b>new_plane</b> which
+has been translated by <b>distance</b> units along the
+direction of the normal. The new plane is also returned as
+plane coefficients.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>face_translate_along_normal</b> is similar, except that
+it also translates a list of points by the same
+distance.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>plane_coefficients(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pmalloc</title>
+</head>
+<body>
+
+<h1 align=center>pmalloc</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#BUGS">BUGS</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:29 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pmalloc, pcalloc, prealloc - allocate memory in a pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void *pmalloc (pool, size_t n);
+void *pcalloc (pool, size_t nmemb, size_t size);
+void *prealloc (pool, void *ptr, size_t n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate memory in a pool or, if pool is null, on the main
+heap (equivalent to plain <b>malloc</b>). If memory is
+allocated in a real pool, then it is automatically freed
+when the pool is deleted.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Memory returned is word-aligned.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+If a memory allocation fails, the <b>bad_malloc_handler</b>
+function is called (which defaults to just calling
+<b>abort(3)</b>).</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pcalloc</b> is identical to <b>pmalloc</b> but also sets
+the memory to zero before returning it.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>prealloc</b> increases the size of an existing memory
+allocation. <b>prealloc</b> might move the memory in the
+process of reallocating it.</td></table>
+<a name="BUGS"></a>
+<h2>BUGS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>prealloc</b> cannot reduce the size of an existing memory
+allocation.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pmatch</title>
+</head>
+<body>
+
+<h1 align=center>pmatch</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:30 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pmatch, pmatchx - test if a string matches a regular expression</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+#define pmatch(p,str,re) pmatchx ((p), (str), (re), REG_EXTENDED, 0, 0)
+vector pmatchx (pool, const char *str, const char *re, int cflags, int eflags, int flags);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmatch</b> is used as a quick way to test if a string
+<b>str</b> matches a POSIX regular expression <b>re</b>. The
+function internally caches compiled regular expressions for
+speed. The function returns a <b>vector</b> of <b>char
+*</b>, containing the list of substrings which match. If the
+regular expression does not match, then <b>NULL</b> is
+returned.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmatchx</b> is the same as <b>pmatch</b> except that it
+allows greater control with flags. <b>cflags</b> and
+<b>eflags</b> are passed directly to <b>regcomp(3)</b> and
+<b>regexec(3)</b> respectively. <b>flags</b> may
+contain:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PMATCH_NO_CACHE</b>: Compile the regular expression
+regardless of whether the <b>re</b> is stored in the cache,
+and do not store the compiled regular expression back into
+the cache. This flag is useful to save memory if you know
+that the particular <b>re</b> will only be used very
+infrequently, and hence storing it in the cache would just
+be a waste of space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Note that the state of <b>cflags</b> is not stored in the
+cache. In rare circumstances this could cause
+problems.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pmatch</title>
+</head>
+<body>
+
+<h1 align=center>pmatch</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:31 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pmatch, pmatchx - test if a string matches a regular expression</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+#define pmatch(p,str,re) pmatchx ((p), (str), (re), REG_EXTENDED, 0, 0)
+vector pmatchx (pool, const char *str, const char *re, int cflags, int eflags, int flags);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmatch</b> is used as a quick way to test if a string
+<b>str</b> matches a POSIX regular expression <b>re</b>. The
+function internally caches compiled regular expressions for
+speed. The function returns a <b>vector</b> of <b>char
+*</b>, containing the list of substrings which match. If the
+regular expression does not match, then <b>NULL</b> is
+returned.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmatchx</b> is the same as <b>pmatch</b> except that it
+allows greater control with flags. <b>cflags</b> and
+<b>eflags</b> are passed directly to <b>regcomp(3)</b> and
+<b>regexec(3)</b> respectively. <b>flags</b> may
+contain:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PMATCH_NO_CACHE</b>: Compile the regular expression
+regardless of whether the <b>re</b> is stored in the cache,
+and do not store the compiled regular expression back into
+the cache. This flag is useful to save memory if you know
+that the particular <b>re</b> will only be used very
+infrequently, and hence storing it in the cache would just
+be a waste of space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Note that the state of <b>cflags</b> is not stored in the
+cache. In rare circumstances this could cause
+problems.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrdup</title>
+</head>
+<body>
+
+<h1 align=center>pstrdup</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:32 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrdup, pstrndup, pmemdup - duplicate a string or area of memory</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pstrdup (pool, const char *s);
+char *pstrndup (pool, const char *s, int n);
+void *pmemdup (pool, const void *data, size_t size);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrdup</b> duplicates string <b>s</b>, allocating new
+memory for the string in pool <b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrndup</b> duplicates just the first <b>n</b>
+characters of the string.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmemdup</b> duplicates an arbitrary area of memory of
+size <b>size</b> bytes starting at address
+<b>data</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>point_distance_to_face</title>
+</head>
+<body>
+
+<h1 align=center>point_distance_to_face</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#RETURNS">RETURNS</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:33 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+point_distance_to_face - distance from point to bounded convex polygon (face)</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float point_distance_to_face (const float *points, int nr_points, const float *plane, const float *point, int *edge);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Given a point and a bounded convex polygon (a
+"face"), the function
+<b>point_distance_to_face</b> calculates the distance from
+the point to the face. There are two importance cases to
+consider here:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+(a) The point is directly above or below the face. In other
+words, a line dropped from the point perpendicular to the
+face intersects the face within the boundary of the polygon.
+In this case, the function returns the shortest distance
+from the point to the intersection (and is essentially
+equivalent to <b>point_distance_to_plane</b>).</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+(b) The point is not directly above or below the face. In
+this case the function works out the distance to the nearest
+edge of the face.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The face is specified as a list of points and a plane (ie.
+plane coefficients). If <b>plane</b> is <b>NULL</b>, then
+the function calls <b>plane_coefficients(3)</b> on your
+behalf. If the face is fixed, and you will call this
+function lots of times, then it is a good idea to calculate
+the plane coefficients once only and cache
+them.</td></table>
+<a name="RETURNS"></a>
+<h2>RETURNS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The distance of the point from the face. The distance will
+be positive if the point is above the face (ie. inside the
+plane: see <b>point_distance_to_plane(3)</b>), or negative
+otherwise.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+If <b>edge</b> is not <b>NULL</b>, then it is set to one of
+the following values:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>*edge == -1</b> if the point is directly above or below
+the face, corresponding to case (a) above.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>*edge == 0 .. nr_points-1</b> if the point is closest to
+that particular edge, corresponding to case (b)
+above.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>point_distance_to_plane(3)</b>,
+<b>plane_coefficients(3)</b>, <b>point_lies_in_face(3)</b>,
+<b>point_distance_to_line(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>point_distance_to_line</title>
+</head>
+<body>
+
+<h1 align=center>point_distance_to_line</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:35 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+point_distance_to_line - shortest distance from a point to a line</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float point_distance_to_line (const float *point, const float *line_point, const float *line_vector);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Given a <b>point</b> and a line, expressed as
+<b>line_point</b> and parallel <b>line_vector</b>, compute
+the shortest distance from the point to the
+line.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>point_distance_to_plane(3)</b>,
+<b>point_distance_to_face(3)</b>,
+<b>point_distance_to_line_segment(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>point_distance_to_line_segment</title>
+</head>
+<body>
+
+<h1 align=center>point_distance_to_line_segment</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:36 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+point_distance_to_line_segment - shortest distance from a point to a line segment</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float point_distance_to_line_segment (const float *point, const float *line_point0, const float *line_point1);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Given a <b>point</b> and a line segment from
+<b>line_point0</b> to <b>line_point1</b>, compute the
+shortest distance from the point to the line
+segment.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>point_distance_to_line(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>point_distance_to_plane</title>
+</head>
+<body>
+
+<h1 align=center>point_distance_to_plane</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:37 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+point_distance_to_plane, point_is_inside_plane - distance from point to plane</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float point_distance_to_plane (const float *plane, const float *point);
+int point_is_inside_plane (const float *plane, const float *point);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>point_distance_to_plane</b> calculates the (shortest)
+distance from the point <b>point</b> to the plane
+<b>plane</b>. This distance is positive if the point is
+"inside" the plane -- that is, if the normal
+vector drawn from the plane points towards the point. It is
+negative if the point is "outside" the plane. It
+is zero if the point lies on the plane.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>point_is_inside_plane</b> returns true if the point is
+strictly inside the plane, and false if the point lies on
+the plane or is outside. It is much faster to compute this
+than to use <b>point_distance_to_plane</b> and take the sign
+of the result.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>plane_coefficients(3)</b>,
+<b>point_distance_to_face(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>point_lies_in_face</title>
+</head>
+<body>
+
+<h1 align=center>point_lies_in_face</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:38 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+point_lies_in_face, point_face_angle_sum - does a point lie on the interior of a bounded convex polygon</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+int point_lies_in_face (const float *points, int nr_points, const float *point);
+float point_face_angle_sum (const float *points, int nr_points, const float *point);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Take a bounded convex polygon (a "face") and a
+point. The function <b>point_lies_in_face</b> returns true
+iff the point is both (a) coplanar with the face, and (b)
+lies inside the edges of the face.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+In order to do this, <b>point_lies_in_face</b> calls
+<b>point_face_angle_sum</b> which works out the sum of the
+interior angles. If conditions (a) and (b) are both
+satisfied then the sum of the interior angles will be very
+close to 2.PI.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The face is expressed as a flat list of points
+(3-vectors).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>plane_coefficients(3)</b>,
+<b>point_distance_to_face(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>point_distance_to_plane</title>
+</head>
+<body>
+
+<h1 align=center>point_distance_to_plane</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:39 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+point_distance_to_plane, point_is_inside_plane - distance from point to plane</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float point_distance_to_plane (const float *plane, const float *point);
+int point_is_inside_plane (const float *plane, const float *point);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>point_distance_to_plane</b> calculates the (shortest)
+distance from the point <b>point</b> to the plane
+<b>plane</b>. This distance is positive if the point is
+"inside" the plane -- that is, if the normal
+vector drawn from the plane points towards the point. It is
+negative if the point is "outside" the plane. It
+is zero if the point lies on the plane.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>point_is_inside_plane</b> returns true if the point is
+strictly inside the plane, and false if the point lies on
+the plane or is outside. It is much faster to compute this
+than to use <b>point_distance_to_plane</b> and take the sign
+of the result.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>plane_coefficients(3)</b>,
+<b>point_distance_to_face(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>point_lies_in_face</title>
+</head>
+<body>
+
+<h1 align=center>point_lies_in_face</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:40 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+point_lies_in_face, point_face_angle_sum - does a point lie on the interior of a bounded convex polygon</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+int point_lies_in_face (const float *points, int nr_points, const float *point);
+float point_face_angle_sum (const float *points, int nr_points, const float *point);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Take a bounded convex polygon (a "face") and a
+point. The function <b>point_lies_in_face</b> returns true
+iff the point is both (a) coplanar with the face, and (b)
+lies inside the edges of the face.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+In order to do this, <b>point_lies_in_face</b> calls
+<b>point_face_angle_sum</b> which works out the sum of the
+interior angles. If conditions (a) and (b) are both
+satisfied then the sum of the interior angles will be very
+close to 2.PI.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The face is expressed as a flat list of points
+(3-vectors).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>plane_coefficients(3)</b>,
+<b>point_distance_to_face(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pool_get_stats</title>
+</head>
+<body>
+
+<h1 align=center>pool_get_stats</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:41 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pool_get_stats - get statistics from the pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void pool_get_stats (const pool, struct pool_stats *stats, size_t n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return various statistics collected for the pool. This
+function fills in the <b>stats</b> argument which should
+point to a structure of type <b>struct pool_stats</b>.
+<b>n</b> should be set to the size of this
+structure.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>struct pool_stats</b> currently contains the following
+fields:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>nr_subpools</b>: The number of subpools (including the
+current pool).</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>struct_size</b>: The memory overhead used by the pool
+allocator itself to store structures. This includes
+subpools.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pool_register_cleanup_fn</title>
+</head>
+<body>
+
+<h1 align=center>pool_register_cleanup_fn</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:42 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pool_register_cleanup_fn - call function when pool is deleted</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void pool_register_cleanup_fn (pool, void (*fn) (void *), void *data);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Register a function to be called when the pool is deleted.
+There is no way to unregister this function. If you wish to
+do that, then you probably want to register it in a
+subpool.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pool_register_fd</title>
+</head>
+<body>
+
+<h1 align=center>pool_register_fd</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:43 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pool_register_fd - allow pool to own file descriptor</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void pool_register_fd (pool, int fd);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Register a file descriptor to be closed when the pool is
+deleted. There is no way to unregister a file descriptor. If
+you wish to do that, then you probably want to register the
+fd in a subpool.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pool_register_malloc</title>
+</head>
+<body>
+
+<h1 align=center>pool_register_malloc</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:44 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pool_register_malloc - allow pool to own malloc'd memory</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void pool_register_malloc (pool, void *ptr);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Register an anonymous area of malloc-allocated memory which
+will be freed (with <b>free(3)</b>) when the pool is
+deleted.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pool_set_bad_malloc_handler</title>
+</head>
+<body>
+
+<h1 align=center>pool_set_bad_malloc_handler</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:45 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pool_set_bad_malloc_handler - set handler for when malloc fails</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void pool_set_bad_malloc_handler (void (*fn) (void));
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Set the function which is called when an underlying malloc
+or realloc operation fails. The default is that
+<b>abort(3)</b> is called.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pmalloc</title>
+</head>
+<body>
+
+<h1 align=center>pmalloc</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#BUGS">BUGS</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:46 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pmalloc, pcalloc, prealloc - allocate memory in a pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pool.h>
+
+void *pmalloc (pool, size_t n);
+void *pcalloc (pool, size_t nmemb, size_t size);
+void *prealloc (pool, void *ptr, size_t n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Allocate memory in a pool or, if pool is null, on the main
+heap (equivalent to plain <b>malloc</b>). If memory is
+allocated in a real pool, then it is automatically freed
+when the pool is deleted.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Memory returned is word-aligned.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+If a memory allocation fails, the <b>bad_malloc_handler</b>
+function is called (which defaults to just calling
+<b>abort(3)</b>).</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pcalloc</b> is identical to <b>pmalloc</b> but also sets
+the memory to zero before returning it.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>prealloc</b> increases the size of an existing memory
+allocation. <b>prealloc</b> might move the memory in the
+process of reallocating it.</td></table>
+<a name="BUGS"></a>
+<h2>BUGS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>prealloc</b> cannot reduce the size of an existing memory
+allocation.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>psort</title>
+</head>
+<body>
+
+<h1 align=center>psort</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:47 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+psort - sort a vector of strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+void psort (vector, int (*compare_fn) (const char **, const char **));
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Sort a vector of strings, using <b>compare_fn</b> to compare
+strings. The vector is sorted in-place.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+It is a common mistake to try to use <b>strcmp</b> directly
+as your comparison function. This will not work. See the C
+FAQ, section 12, question 12.2
+(<b>http://www.lysator.liu.se/c/c-faq/c-12.html</b>).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>psprintf</title>
+</head>
+<body>
+
+<h1 align=center>psprintf</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:48 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+psprintf, pvsprintf - sprintf which allocates the result in a pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *psprintf (pool, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+char *pvsprintf (pool, const char *format, va_list ap);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>psprintf</b> function is equivalent to <b>sprintf</b>
+but it allocates the result string in
+<b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvsprintf</b> works similarly to
+<b>vsprintf</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrcat</title>
+</head>
+<body>
+
+<h1 align=center>pstrcat</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:49 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrcat, pstrncat - extend a string</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pstrcat (pool, char *str, const char *ending);
+char *pstrncat (pool, char *str, const char *ending, size_t n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>str</b> is a string allocated in <b>pool</b>. Append
+<b>ending</b> to <b>str</b>, reallocating <b>str</b> if
+necessary.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Because <b>str</b> may be reallocated (ie. moved) you must
+invoke this function as follows:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>str = pstrcat (pool, str, ending);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrncat</b> is similar to <b>pstrcat</b> except that
+only the first <b>n</b> characters of <b>ending</b> are
+appended to <b>str</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrsplit</title>
+</head>
+<body>
+
+<h1 align=center>pstrsplit</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:50 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrsplit, pstrcsplit, pstrresplit - split a string on a character, string or regexp.</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+vector pstrsplit (pool, const char *str, const char *sep);
+vector pstrcsplit (pool, const char *str, char c);
+vector pstrresplit (pool, const char *str, const regex_t *re);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+These functions split string <b>str</b> on either a string
+<b>sep</b>, a character <b>c</b> or a regular expression
+<b>re</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The result is a vector of newly created
+substrings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Perl's <b>split</b> function treats zero-length strings
+differently from other strings -- returning an empty vector
+(rather than returning a vector containing a single
+zero-length string which is what you might expect, and is
+slightly more orthogonal). The author has not decided what
+the correct behaviour should be, so treat this case as
+undefined in the current release.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrdup</title>
+</head>
+<body>
+
+<h1 align=center>pstrdup</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:51 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrdup, pstrndup, pmemdup - duplicate a string or area of memory</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pstrdup (pool, const char *s);
+char *pstrndup (pool, const char *s, int n);
+void *pmemdup (pool, const void *data, size_t size);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrdup</b> duplicates string <b>s</b>, allocating new
+memory for the string in pool <b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrndup</b> duplicates just the first <b>n</b>
+characters of the string.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmemdup</b> duplicates an arbitrary area of memory of
+size <b>size</b> bytes starting at address
+<b>data</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrupr</title>
+</head>
+<body>
+
+<h1 align=center>pstrupr</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:52 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrupr, pstrlwr - convert a string to upper- or lowercase</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pstrupr (char *str);
+char *pstrlwr (char *str);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Convert a string, in-place, to upper or lowercase by
+applying <b>toupper</b> or <b>tolower</b> to each character
+in turn.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrcat</title>
+</head>
+<body>
+
+<h1 align=center>pstrcat</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:53 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrcat, pstrncat - extend a string</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pstrcat (pool, char *str, const char *ending);
+char *pstrncat (pool, char *str, const char *ending, size_t n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>str</b> is a string allocated in <b>pool</b>. Append
+<b>ending</b> to <b>str</b>, reallocating <b>str</b> if
+necessary.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Because <b>str</b> may be reallocated (ie. moved) you must
+invoke this function as follows:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>str = pstrcat (pool, str, ending);</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrncat</b> is similar to <b>pstrcat</b> except that
+only the first <b>n</b> characters of <b>ending</b> are
+appended to <b>str</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrdup</title>
+</head>
+<body>
+
+<h1 align=center>pstrdup</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:54 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrdup, pstrndup, pmemdup - duplicate a string or area of memory</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pstrdup (pool, const char *s);
+char *pstrndup (pool, const char *s, int n);
+void *pmemdup (pool, const void *data, size_t size);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrdup</b> duplicates string <b>s</b>, allocating new
+memory for the string in pool <b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrndup</b> duplicates just the first <b>n</b>
+characters of the string.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pmemdup</b> duplicates an arbitrary area of memory of
+size <b>size</b> bytes starting at address
+<b>data</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrsplit</title>
+</head>
+<body>
+
+<h1 align=center>pstrsplit</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:56 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrsplit, pstrcsplit, pstrresplit - split a string on a character, string or regexp.</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+vector pstrsplit (pool, const char *str, const char *sep);
+vector pstrcsplit (pool, const char *str, char c);
+vector pstrresplit (pool, const char *str, const regex_t *re);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+These functions split string <b>str</b> on either a string
+<b>sep</b>, a character <b>c</b> or a regular expression
+<b>re</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The result is a vector of newly created
+substrings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Perl's <b>split</b> function treats zero-length strings
+differently from other strings -- returning an empty vector
+(rather than returning a vector containing a single
+zero-length string which is what you might expect, and is
+slightly more orthogonal). The author has not decided what
+the correct behaviour should be, so treat this case as
+undefined in the current release.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pchrs</title>
+</head>
+<body>
+
+<h1 align=center>pchrs</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:57:58 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pchrs, pstrs - generate a string of n repeated characters or strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pchrs (pool, char c, int n);
+char *pstrs (pool, const char *str, int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pchrs (pool, 'c', n)</b> is similar to the Perl
+expression <b>'c' x n</b>. It generates a pool-allocated
+string of <b>n</b> copies of character
+<b>'c'</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pstrs (pool, str, n)</b> is similar to the Perl
+expression <b>str x n</b>. It generates a pool-allocated
+string of <b>n</b> copies of the string
+<b>str</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrsplit</title>
+</head>
+<body>
+
+<h1 align=center>pstrsplit</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:02 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrsplit, pstrcsplit, pstrresplit - split a string on a character, string or regexp.</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+vector pstrsplit (pool, const char *str, const char *sep);
+vector pstrcsplit (pool, const char *str, char c);
+vector pstrresplit (pool, const char *str, const regex_t *re);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+These functions split string <b>str</b> on either a string
+<b>sep</b>, a character <b>c</b> or a regular expression
+<b>re</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The result is a vector of newly created
+substrings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Perl's <b>split</b> function treats zero-length strings
+differently from other strings -- returning an empty vector
+(rather than returning a vector containing a single
+zero-length string which is what you might expect, and is
+slightly more orthogonal). The author has not decided what
+the correct behaviour should be, so treat this case as
+undefined in the current release.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pstrupr</title>
+</head>
+<body>
+
+<h1 align=center>pstrupr</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:03 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pstrupr, pstrlwr - convert a string to upper- or lowercase</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pstrupr (char *str);
+char *pstrlwr (char *str);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Convert a string, in-place, to upper or lowercase by
+applying <b>toupper</b> or <b>tolower</b> to each character
+in turn.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>psubst</title>
+</head>
+<body>
+
+<h1 align=center>psubst</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:04 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+psubst, psubstx - substitute string matching regular expression</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+#define psubst(p,str,pat,sub) psubstx ((p), (str), (pat), (sub), REG_EXTENDED, 0, 0)
+const char *psubstx (pool, const char *str, const char *pat, const char *sub, int cflags, int eflags, int flags);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>psubst</b> is used as a quick way to substitute strings
+which match a regular expression with other strings. It is
+the equivalent of the <b>s///</b> operator in Perl. The
+function internally caches compiled regular expressions for
+speed. The function returns a new string which is formed
+from <b>str</b> by substituting string <b>sub</b> for the
+first regular expression which matches
+<b>pat</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>psubstx</b> is the same as <b>psubst</b> except that it
+allows greater control with flags. <b>cflags</b> and
+<b>eflags</b> are passed directly to <b>regcomp(3)</b> and
+<b>regexec(3)</b> respectively. <b>flags</b> may
+contain:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PSUBST_GLOBAL</b>: Match and replace every instance of
+<b>pat</b> in the string, not just the first.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PSUBST_NO_CACHE</b>: Compile the regular expression
+regardless of whether the <b>re</b> is stored in the cache,
+and do not store the compiled regular expression back into
+the cache. This flag is useful to save memory if you know
+that the particular <b>re</b> will only be used very
+infrequently, and hence storing it in the cache would just
+be a waste of space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Note that the state of <b>cflags</b> is not stored in the
+cache. In rare circumstances this could cause
+problems.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>psubstr</title>
+</head>
+<body>
+
+<h1 align=center>psubstr</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:05 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+psubstr - return a substring of a string</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *psubstr (pool, const char *str, int offset, int len);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the substring starting at <b>offset</b> and of length
+<b>len</b> of <b>str</b>, allocated as a new string. If
+<b>len</b> is negative, everything up to the end of
+<b>str</b> is returned.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>psubst</title>
+</head>
+<body>
+
+<h1 align=center>psubst</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:06 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+psubst, psubstx - substitute string matching regular expression</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+#define psubst(p,str,pat,sub) psubstx ((p), (str), (pat), (sub), REG_EXTENDED, 0, 0)
+const char *psubstx (pool, const char *str, const char *pat, const char *sub, int cflags, int eflags, int flags);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>psubst</b> is used as a quick way to substitute strings
+which match a regular expression with other strings. It is
+the equivalent of the <b>s///</b> operator in Perl. The
+function internally caches compiled regular expressions for
+speed. The function returns a new string which is formed
+from <b>str</b> by substituting string <b>sub</b> for the
+first regular expression which matches
+<b>pat</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>psubstx</b> is the same as <b>psubst</b> except that it
+allows greater control with flags. <b>cflags</b> and
+<b>eflags</b> are passed directly to <b>regcomp(3)</b> and
+<b>regexec(3)</b> respectively. <b>flags</b> may
+contain:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PSUBST_GLOBAL</b>: Match and replace every instance of
+<b>pat</b> in the string, not just the first.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>PSUBST_NO_CACHE</b>: Compile the regular expression
+regardless of whether the <b>re</b> is stored in the cache,
+and do not store the compiled regular expression back into
+the cache. This flag is useful to save memory if you know
+that the particular <b>re</b> will only be used very
+infrequently, and hence storing it in the cache would just
+be a waste of space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Note that the state of <b>cflags</b> is not stored in the
+cache. In rare circumstances this could cause
+problems.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>ptrim</title>
+</head>
+<body>
+
+<h1 align=center>ptrim</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:07 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+ptrim, ptrimfront, ptrimback - remove whitespace from the ends of a string</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *ptrim (char *str);
+char *ptrimfront (char *str);
+char *ptrimback (char *str);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrim</b> modifies a string of text in place, removing
+any whitespace characters from the beginning and end of the
+line.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrimfront</b> is the same as <b>ptrim</b> but only
+removes whitespace from the beginning of a
+string.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrimback</b> is the same as <b>ptrim</b> but only
+removes whitespace from the end of a string.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>ptrim</title>
+</head>
+<body>
+
+<h1 align=center>ptrim</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:09 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+ptrim, ptrimfront, ptrimback - remove whitespace from the ends of a string</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *ptrim (char *str);
+char *ptrimfront (char *str);
+char *ptrimback (char *str);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrim</b> modifies a string of text in place, removing
+any whitespace characters from the beginning and end of the
+line.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrimfront</b> is the same as <b>ptrim</b> but only
+removes whitespace from the beginning of a
+string.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrimback</b> is the same as <b>ptrim</b> but only
+removes whitespace from the end of a string.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>ptrim</title>
+</head>
+<body>
+
+<h1 align=center>ptrim</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:10 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+ptrim, ptrimfront, ptrimback - remove whitespace from the ends of a string</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *ptrim (char *str);
+char *ptrimfront (char *str);
+char *ptrimback (char *str);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrim</b> modifies a string of text in place, removing
+any whitespace characters from the beginning and end of the
+line.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrimfront</b> is the same as <b>ptrim</b> but only
+removes whitespace from the beginning of a
+string.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>ptrimback</b> is the same as <b>ptrim</b> but only
+removes whitespace from the end of a string.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pvitostr</title>
+</head>
+<body>
+
+<h1 align=center>pvitostr</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:11 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pvitostr, pvdtostr, pvxtostr - convert vectors of numbers to vectors of strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+vector pvitostr (pool, vector);
+vector pvdtostr (pool, vector);
+vector pvxtostr (pool, vector);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Promote vector of numbers to vector of strings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvitostr</b> expects a vector of <b>int</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvdtostr</b> expects a vector of
+<b>double</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvxtostr</b> expects a vector of hexadecimal
+<b>unsigned</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+All functions return a vector of <b>char *</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pvector</title>
+</head>
+<body>
+
+<h1 align=center>pvector</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:12 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pvector, pvectora - generate a vector from a list or array of strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+vector pvector (pool, ...);
+vector pvectora (pool, const char *array[], int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvector</b> takes a NULL-terminated list of strings as
+arguments and returns a vector of strings. <b>pvectora</b>
+takes a pointer to an array of strings and the number of
+strings and returns a vector of strings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+A typical use of this is to quickly concatenate
+strings:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>s = pconcat (pool, pvector (pool, s1, s2, s3,
+NULL));</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+which is roughly equivalent to:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>s = psprintf (pool, "%s%s%s", s1, s2,
+s3);</b></td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pconcat(3)</b>, <b>psprintf(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pvector</title>
+</head>
+<body>
+
+<h1 align=center>pvector</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:13 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pvector, pvectora - generate a vector from a list or array of strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+vector pvector (pool, ...);
+vector pvectora (pool, const char *array[], int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvector</b> takes a NULL-terminated list of strings as
+arguments and returns a vector of strings. <b>pvectora</b>
+takes a pointer to an array of strings and the number of
+strings and returns a vector of strings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+A typical use of this is to quickly concatenate
+strings:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>s = pconcat (pool, pvector (pool, s1, s2, s3,
+NULL));</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+which is roughly equivalent to:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>s = psprintf (pool, "%s%s%s", s1, s2,
+s3);</b></td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pconcat(3)</b>, <b>psprintf(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pvitostr</title>
+</head>
+<body>
+
+<h1 align=center>pvitostr</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:14 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pvitostr, pvdtostr, pvxtostr - convert vectors of numbers to vectors of strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+vector pvitostr (pool, vector);
+vector pvdtostr (pool, vector);
+vector pvxtostr (pool, vector);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Promote vector of numbers to vector of strings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvitostr</b> expects a vector of <b>int</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvdtostr</b> expects a vector of
+<b>double</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvxtostr</b> expects a vector of hexadecimal
+<b>unsigned</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+All functions return a vector of <b>char *</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>psprintf</title>
+</head>
+<body>
+
+<h1 align=center>psprintf</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:15 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+psprintf, pvsprintf - sprintf which allocates the result in a pool</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *psprintf (pool, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+char *pvsprintf (pool, const char *format, va_list ap);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>psprintf</b> function is equivalent to <b>sprintf</b>
+but it allocates the result string in
+<b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvsprintf</b> works similarly to
+<b>vsprintf</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pvitostr</title>
+</head>
+<body>
+
+<h1 align=center>pvitostr</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:16 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pvitostr, pvdtostr, pvxtostr - convert vectors of numbers to vectors of strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+vector pvitostr (pool, vector);
+vector pvdtostr (pool, vector);
+vector pvxtostr (pool, vector);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Promote vector of numbers to vector of strings.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvitostr</b> expects a vector of <b>int</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvdtostr</b> expects a vector of
+<b>double</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pvxtostr</b> expects a vector of hexadecimal
+<b>unsigned</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+All functions return a vector of <b>char *</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>pitoa</title>
+</head>
+<body>
+
+<h1 align=center>pitoa</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:17 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+pitoa, pdtoa, pxtoa - convert number types to strings</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <pstring.h>
+
+char *pitoa (pool, int);
+char *pdtoa (pool, double);
+char *pxtoa (pool, unsigned);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+These functions convert a decimal <b>int</b>, <b>double</b>
+or hexadecimal <b>unsigned</b> into a string, which is
+allocated in <b>pool</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>pitoa</b> is equivalent to <b>psprintf (pool,
+"%d", i)</b>, and the other functions have similar
+equivalents.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_erase</title>
+</head>
+<body>
+
+<h1 align=center>sash_erase</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:18 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_erase - erase a key from a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int sash_erase (sash, const char *key);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Erase <b>key</b> from the sash. If an element was erased,
+this returns true, else this returns false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_get</title>
+</head>
+<body>
+
+<h1 align=center>sash_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:19 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_get, _sash_get, sash_exists - look up in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define sash_get(sash,key,value) _sash_get((sash),(key),&(value))
+int _sash_get (sash, const char *key, const char **ptr);
+#define sash_exists(sash,key) _sash_get ((sash), (key), 0)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Get the <b>value</b> associated with key <b>key</b> and
+return true. If there is no <b>value</b> associated with
+<b>key</b>, this returns false and <b>value</b> is left
+unchanged.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>sash_exists</b> simply tests whether or not <b>key</b>
+exists in the sash. If so, it returns true, otherwise
+false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_get</title>
+</head>
+<body>
+
+<h1 align=center>sash_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:20 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_get, _sash_get, sash_exists - look up in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define sash_get(sash,key,value) _sash_get((sash),(key),&(value))
+int _sash_get (sash, const char *key, const char **ptr);
+#define sash_exists(sash,key) _sash_get ((sash), (key), 0)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Get the <b>value</b> associated with key <b>key</b> and
+return true. If there is no <b>value</b> associated with
+<b>key</b>, this returns false and <b>value</b> is left
+unchanged.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>sash_exists</b> simply tests whether or not <b>key</b>
+exists in the sash. If so, it returns true, otherwise
+false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_get_buckets_used</title>
+</head>
+<body>
+
+<h1 align=center>sash_get_buckets_used</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:21 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_get_buckets_used, sash_get_buckets_allocated - return the number of buckets in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int sash_get_buckets_used (sash);
+int sash_get_buckets_allocated (sash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the number of sash buckets used and allocated. The
+number of buckets allocated is always a power of 2. See also
+<b>sash_set_buckets_allocated</b> to change the number used
+in the sash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_get_buckets_used</title>
+</head>
+<body>
+
+<h1 align=center>sash_get_buckets_used</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:22 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_get_buckets_used, sash_get_buckets_allocated - return the number of buckets in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int sash_get_buckets_used (sash);
+int sash_get_buckets_allocated (sash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the number of sash buckets used and allocated. The
+number of buckets allocated is always a power of 2. See also
+<b>sash_set_buckets_allocated</b> to change the number used
+in the sash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_insert</title>
+</head>
+<body>
+
+<h1 align=center>sash_insert</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:23 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_insert - insert a (key, value) pair into a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int sash_insert (sash, const char *key, const char *value);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Insert an element (<b>key</b>, <b>value</b>) into the sash.
+If <b>key</b> already exists in the sash, then the existing
+value is replaced by <b>value</b> and the function returns
+true. If there was no previous <b>key</b> in the sash then
+this function returns false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_keys</title>
+</head>
+<body>
+
+<h1 align=center>sash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:24 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_keys, sash_keys_in_pool, sash_values, sash_values_in_pool - return a vector of the keys or values in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector sash_keys (sash);
+vector sash_keys_in_pool (sash, pool);
+vector sash_values (sash);
+vector sash_values_in_pool (sash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of sash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the sash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_keys</title>
+</head>
+<body>
+
+<h1 align=center>sash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:25 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_keys, sash_keys_in_pool, sash_values, sash_values_in_pool - return a vector of the keys or values in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector sash_keys (sash);
+vector sash_keys_in_pool (sash, pool);
+vector sash_values (sash);
+vector sash_values_in_pool (sash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of sash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the sash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_set_buckets_allocated</title>
+</head>
+<body>
+
+<h1 align=center>sash_set_buckets_allocated</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:26 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_set_buckets_allocated - set the number of buckets</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+void sash_set_buckets_allocated (sash, int);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Set the number of buckets allocated. You may ONLY do this
+when you have just created the sash and before you have
+inserted any elements. Otherwise the results are undefined
+(and probably bad). The number of buckets MUST be a power of
+2.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_size</title>
+</head>
+<body>
+
+<h1 align=center>sash_size</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:27 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_size - return the number of (key, value) pairs in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int sash_size (sash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Count the number of (key, value) pairs in the
+sash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_keys</title>
+</head>
+<body>
+
+<h1 align=center>sash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:28 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_keys, sash_keys_in_pool, sash_values, sash_values_in_pool - return a vector of the keys or values in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector sash_keys (sash);
+vector sash_keys_in_pool (sash, pool);
+vector sash_values (sash);
+vector sash_values_in_pool (sash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of sash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the sash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>sash_keys</title>
+</head>
+<body>
+
+<h1 align=center>sash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:29 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+sash_keys, sash_keys_in_pool, sash_values, sash_values_in_pool - return a vector of the keys or values in a sash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector sash_keys (sash);
+vector sash_keys_in_pool (sash, pool);
+vector sash_values (sash);
+vector sash_values_in_pool (sash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of sash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the sash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_erase</title>
+</head>
+<body>
+
+<h1 align=center>shash_erase</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:30 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_erase - erase a key from a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int shash_erase (shash, const char *key);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Erase <b>key</b> from the shash. If an element was erased,
+this returns true, else this returns false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_get</title>
+</head>
+<body>
+
+<h1 align=center>shash_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:32 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_get, _shash_get, shash_get_ptr, _shash_get_ptr, shash_exists - look up in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define shash_get(shash,key,value) _shash_get((shash),(key),&(value))
+int _shash_get (shash, const char *key, void *value);
+#define shash_get_ptr(h,key,ptr) _shash_get_ptr ((h),(key),&(ptr))
+int _shash_get_ptr (shash, const char *key, void **ptr);
+#define shash_exists(shash,key) _shash_get_ptr ((shash), (key), 0)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Get the <b>value</b> associated with key <b>key</b> and
+return true. If there is no <b>value</b> associated with
+<b>key</b>, this returns false and <b>value</b> is left
+unchanged.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_ptr</b> variants return a pointer rather than
+copying out the entire value object. The pointer is
+typically only valid for a short period of time.
+Particularly if you insert or remove elements from the
+shash, this pointer may become invalid.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>shash_exists</b> simply tests whether or not <b>key</b>
+exists in the shash. If so, it returns true, otherwise
+false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_get</title>
+</head>
+<body>
+
+<h1 align=center>shash_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:33 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_get, _shash_get, shash_get_ptr, _shash_get_ptr, shash_exists - look up in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define shash_get(shash,key,value) _shash_get((shash),(key),&(value))
+int _shash_get (shash, const char *key, void *value);
+#define shash_get_ptr(h,key,ptr) _shash_get_ptr ((h),(key),&(ptr))
+int _shash_get_ptr (shash, const char *key, void **ptr);
+#define shash_exists(shash,key) _shash_get_ptr ((shash), (key), 0)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Get the <b>value</b> associated with key <b>key</b> and
+return true. If there is no <b>value</b> associated with
+<b>key</b>, this returns false and <b>value</b> is left
+unchanged.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_ptr</b> variants return a pointer rather than
+copying out the entire value object. The pointer is
+typically only valid for a short period of time.
+Particularly if you insert or remove elements from the
+shash, this pointer may become invalid.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>shash_exists</b> simply tests whether or not <b>key</b>
+exists in the shash. If so, it returns true, otherwise
+false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_get_buckets_used</title>
+</head>
+<body>
+
+<h1 align=center>shash_get_buckets_used</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:34 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_get_buckets_used, shash_get_buckets_allocated - return the number of buckets in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int shash_get_buckets_used (shash);
+int shash_get_buckets_allocated (shash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the number of shash buckets used and allocated. The
+number of buckets allocated is always a power of 2. See also
+<b>shash_set_buckets_allocated</b> to change the number used
+in the shash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_get_buckets_used</title>
+</head>
+<body>
+
+<h1 align=center>shash_get_buckets_used</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:35 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_get_buckets_used, shash_get_buckets_allocated - return the number of buckets in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int shash_get_buckets_used (shash);
+int shash_get_buckets_allocated (shash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the number of shash buckets used and allocated. The
+number of buckets allocated is always a power of 2. See also
+<b>shash_set_buckets_allocated</b> to change the number used
+in the shash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_get</title>
+</head>
+<body>
+
+<h1 align=center>shash_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:36 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_get, _shash_get, shash_get_ptr, _shash_get_ptr, shash_exists - look up in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define shash_get(shash,key,value) _shash_get((shash),(key),&(value))
+int _shash_get (shash, const char *key, void *value);
+#define shash_get_ptr(h,key,ptr) _shash_get_ptr ((h),(key),&(ptr))
+int _shash_get_ptr (shash, const char *key, void **ptr);
+#define shash_exists(shash,key) _shash_get_ptr ((shash), (key), 0)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Get the <b>value</b> associated with key <b>key</b> and
+return true. If there is no <b>value</b> associated with
+<b>key</b>, this returns false and <b>value</b> is left
+unchanged.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_ptr</b> variants return a pointer rather than
+copying out the entire value object. The pointer is
+typically only valid for a short period of time.
+Particularly if you insert or remove elements from the
+shash, this pointer may become invalid.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>shash_exists</b> simply tests whether or not <b>key</b>
+exists in the shash. If so, it returns true, otherwise
+false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_insert</title>
+</head>
+<body>
+
+<h1 align=center>shash_insert</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:37 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_insert, _shash_insert - insert a (key, value) pair into a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+#define shash_insert(h,key,value) _shash_insert((h),(key),&(value))
+int _shash_insert (shash, const char *key, const void *value);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Insert an element (<b>key</b>, <b>value</b>) into the shash.
+If <b>key</b> already exists in the shash, then the existing
+value is replaced by <b>value</b> and the function returns
+true. If there was no previous <b>key</b> in the shash then
+this function returns false.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_keys</title>
+</head>
+<body>
+
+<h1 align=center>shash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:38 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_keys, shash_keys_in_pool, shash_values, shash_values_in_pool - return a vector of the keys or values in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector shash_keys (shash);
+vector shash_keys_in_pool (shash, pool);
+vector shash_values (shash);
+vector shash_values_in_pool (shash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of shash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the shash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_keys</title>
+</head>
+<body>
+
+<h1 align=center>shash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:39 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_keys, shash_keys_in_pool, shash_values, shash_values_in_pool - return a vector of the keys or values in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector shash_keys (shash);
+vector shash_keys_in_pool (shash, pool);
+vector shash_values (shash);
+vector shash_values_in_pool (shash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of shash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the shash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_set_buckets_allocated</title>
+</head>
+<body>
+
+<h1 align=center>shash_set_buckets_allocated</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:40 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_set_buckets_allocated - set the number of buckets</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+void shash_set_buckets_allocated (shash, int);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Set the number of buckets allocated. You may ONLY do this
+when you have just created the shash and before you have
+inserted any elements. Otherwise the results are undefined
+(and probably bad). The number of buckets MUST be a power of
+2.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_size</title>
+</head>
+<body>
+
+<h1 align=center>shash_size</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:41 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_size - return the number of (key, value) pairs in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+int shash_size (shash);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Count the number of (key, value) pairs in the
+shash.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_keys</title>
+</head>
+<body>
+
+<h1 align=center>shash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:42 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_keys, shash_keys_in_pool, shash_values, shash_values_in_pool - return a vector of the keys or values in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector shash_keys (shash);
+vector shash_keys_in_pool (shash, pool);
+vector shash_values (shash);
+vector shash_values_in_pool (shash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of shash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the shash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>shash_keys</title>
+</head>
+<body>
+
+<h1 align=center>shash_keys</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:43 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+shash_keys, shash_keys_in_pool, shash_values, shash_values_in_pool - return a vector of the keys or values in a shash</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <hash.h>
+
+vector shash_keys (shash);
+vector shash_keys_in_pool (shash, pool);
+vector shash_values (shash);
+vector shash_values_in_pool (shash, pool);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return a vector containing all the keys or values of shash.
+The <b>*_in_pool</b> variants allow you to allocate the
+vector in another pool (the default is to allocate the
+vector in the same pool as the shash).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vec_angle_between</title>
+</head>
+<body>
+
+<h1 align=center>vec_angle_between</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:44 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vec_angle_between - calculate the angle between two vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float vec_angle_between (const float *v1, const float *v2);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+This function returns the angle between two vectors
+<b>v1</b> and <b>v2</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_dot_product(3)</b>,
+<b>vec_magnitude_in_direction(3)</b></td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vec_dot_product</title>
+</head>
+<body>
+
+<h1 align=center>vec_dot_product</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:45 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vec_dot_product - calculate the dot product of two vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float vec_dot_product (const float *v1, const float *v2);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_dot_product</b> calculates the dot product of two
+vectors <b>v1</b> and <b>v2</b> and returns it. The dot
+product is formally defined as:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>|v1| |v2| cos theta</b></td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+where <b>theta</b> is the angle between the two
+vectors.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+One interesting consequence of this is that if both
+<b>v1</b> and <b>v2</b> are already normalized, then the dot
+product is 1 if the vectors are parallel and running in the
+same direction, and 0 if the vectors are
+perpendicular.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_magnitude_in_direction(3)</b>,
+<b>vec_angle_between(3)</b></td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vec_magnitude</title>
+</head>
+<body>
+
+<h1 align=center>vec_magnitude</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:46 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vec_magnitude, vec_magnitude2d - calculate magnitude (length) of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float vec_magnitude (const float *v);
+float vec_magnitude2d (const float *v);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_magnitude</b> calculates the magnitude (length) of a
+3D vector. <b>vec_magnitude2d</b> calculates the magnitude
+of a 2D vector.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_normalize(3)</b>,
+<b>vec_normalize2d(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vec_magnitude</title>
+</head>
+<body>
+
+<h1 align=center>vec_magnitude</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:47 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vec_magnitude, vec_magnitude2d - calculate magnitude (length) of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float vec_magnitude (const float *v);
+float vec_magnitude2d (const float *v);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_magnitude</b> calculates the magnitude (length) of a
+3D vector. <b>vec_magnitude2d</b> calculates the magnitude
+of a 2D vector.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_normalize(3)</b>,
+<b>vec_normalize2d(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vec_magnitude_in_direction</title>
+</head>
+<body>
+
+<h1 align=center>vec_magnitude_in_direction</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:48 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vec_magnitude_in_direction - calculate relative direction of two vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float vec_magnitude_in_direction (const float *v1, const float *v2);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+If <b>v1</b> and <b>v2</b> are parallel and point in the
+same direction, then <b>vec_magnitude_in_direction</b>
+returns +1. If <b>v1</b> and <b>v2</b> are perpendicular,
+this returns 0. If <b>v1</b> and <b>v2</b> are parallel and
+point in opposite directions to each other, this returns -1.
+For other vectors, this function returns the cosine of the
+angle between the vectors.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_dot_product(3)</b>,
+<b>vec_angle_between(3)</b></td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vec_normalize</title>
+</head>
+<body>
+
+<h1 align=center>vec_normalize</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:49 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vec_normalize, vec_normalize2d - normalize a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+void vec_normalize (const float *v, float *r);
+void vec_normalize2d (const float *v, float *r);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+These two functions normalize respectively a 3D or 2D vector
+<b>v</b>. The original vector <b>v</b> is not touched, and
+the result is placed in vector <b>r</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+To normalize a vector in-place (ie. modifying the original
+vector), do:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_normalize (v, v);</b></td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_magnitude(3)</b>,
+<b>vec_magnitude2d(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vec_normalize</title>
+</head>
+<body>
+
+<h1 align=center>vec_normalize</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:50 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vec_normalize, vec_normalize2d - normalize a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+void vec_normalize (const float *v, float *r);
+void vec_normalize2d (const float *v, float *r);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+These two functions normalize respectively a 3D or 2D vector
+<b>v</b>. The original vector <b>v</b> is not touched, and
+the result is placed in vector <b>r</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+To normalize a vector in-place (ie. modifying the original
+vector), do:</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_normalize (v, v);</b></td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vec_magnitude(3)</b>,
+<b>vec_magnitude2d(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_allocated</title>
+</head>
+<body>
+
+<h1 align=center>vector_allocated</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:51 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_allocated - return the space allocated to a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_allocated(v) ((v)->allocated)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the amount of space which has been allocated for
+storing elements of the vector. This is different from the
+number of elements actually stored by the vector (see
+<b>vector_size(3)</b>) and also different from the size of
+each element in bytes (see
+<b>vector_element_size(3)</b>).</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_erase</title>
+</head>
+<body>
+
+<h1 align=center>vector_erase</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:52 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_erase, vector_erase_range, vector_clear - erase elements of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+void vector_erase (vector v, int i);
+void vector_erase_range (vector v, int i, int j);
+void vector_clear (vector v);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_erase</b> removes the element <b>v[i]</b>,
+shuffling the later elements down by one place to fill the
+space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_erase_range</b> removes a range of elements
+<b>v[i]</b> to <b>v[j-1]</b> (<b>i <= j</b>), shuffling
+later elements down to fill the space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_clear</b> removes all elements from the vector,
+setting its size to <b>0</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_compare</title>
+</head>
+<body>
+
+<h1 align=center>vector_compare</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:53 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_compare, _vector_compare - compare two vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_compare(v1,v2,compare_fn) _vector_compare ((v1), (v2), (int (*)(const void *,const void *)) (compare_fn))
+int _vector_compare (vector, vector, int (*compare_fn) (const void *, const void *));
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Compare two vectors. This returns 0 if the two vectors are
+identical. It returns > 0 if <b>v1</b> > <b>v2</b>.
+This returns < 0 if <b>v1</b> <
+<b>v2</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_element_size</title>
+</head>
+<body>
+
+<h1 align=center>vector_element_size</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:54 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_element_size - return the size of each element of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_element_size(v) ((v)->size)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the size in bytes of each element in
+vector.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_erase</title>
+</head>
+<body>
+
+<h1 align=center>vector_erase</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:55 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_erase, vector_erase_range, vector_clear - erase elements of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+void vector_erase (vector v, int i);
+void vector_erase_range (vector v, int i, int j);
+void vector_clear (vector v);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_erase</b> removes the element <b>v[i]</b>,
+shuffling the later elements down by one place to fill the
+space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_erase_range</b> removes a range of elements
+<b>v[i]</b> to <b>v[j-1]</b> (<b>i <= j</b>), shuffling
+later elements down to fill the space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_clear</b> removes all elements from the vector,
+setting its size to <b>0</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_erase</title>
+</head>
+<body>
+
+<h1 align=center>vector_erase</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:56 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_erase, vector_erase_range, vector_clear - erase elements of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+void vector_erase (vector v, int i);
+void vector_erase_range (vector v, int i, int j);
+void vector_clear (vector v);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_erase</b> removes the element <b>v[i]</b>,
+shuffling the later elements down by one place to fill the
+space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_erase_range</b> removes a range of elements
+<b>v[i]</b> to <b>v[j-1]</b> (<b>i <= j</b>), shuffling
+later elements down to fill the space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_clear</b> removes all elements from the vector,
+setting its size to <b>0</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_fill</title>
+</head>
+<body>
+
+<h1 align=center>vector_fill</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:57 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_fill, _vector_fill - fill a vector with identical elements</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_fill(v,obj,n) _vector_fill((v),&(obj),(n))
+void _vector_fill (vector, const void *ptr, int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_fill</b> appends <b>n</b> identical copies of
+<b>obj</b> to the vector. It is equivalent to calling
+<b>vector_push_back(3)</b> in a loop <b>n</b>
+times.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_get</title>
+</head>
+<body>
+
+<h1 align=center>vector_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:58 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_get, _vector_get, vector_get_ptr, _vector_get_ptr - array-style indexing for vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_get(v,i,obj) _vector_get((v),(i),&(obj))
+void _vector_get (vector, int i, void *ptr);
+#define vector_get_ptr(v,i,ptr) (ptr) =((typeof (ptr))_vector_get_ptr((v),(i)))
+const void *_vector_get_ptr (vector, int i);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_get</b> copies the element at index <b>v[i]</b>
+into local variable <b>obj</b>. The vector is
+unaffected.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>_vector_get</b> copies the element into the memory
+pointed to by <b>ptr</b>. If <b>ptr</b> is <b>NULL</b> then
+the effect is simply to check that element <b>v[i]</b>
+exists.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_get_ptr</b> and <b>_vector_get_ptr</b> are used to
+get a pointer to an element in the vector. This pointer
+actually points to the vector's internal data array. It is
+only valid as long as the user does not cause the internal
+data array to be reallocated or moved - typically this can
+happen when the user performs some operation which inserts
+more elements into the array.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked. An attempt to access an
+out-of-bounds element will result in a call to
+<b>abort(3)</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_get</title>
+</head>
+<body>
+
+<h1 align=center>vector_get</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:58:59 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_get, _vector_get, vector_get_ptr, _vector_get_ptr - array-style indexing for vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_get(v,i,obj) _vector_get((v),(i),&(obj))
+void _vector_get (vector, int i, void *ptr);
+#define vector_get_ptr(v,i,ptr) (ptr) =((typeof (ptr))_vector_get_ptr((v),(i)))
+const void *_vector_get_ptr (vector, int i);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_get</b> copies the element at index <b>v[i]</b>
+into local variable <b>obj</b>. The vector is
+unaffected.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>_vector_get</b> copies the element into the memory
+pointed to by <b>ptr</b>. If <b>ptr</b> is <b>NULL</b> then
+the effect is simply to check that element <b>v[i]</b>
+exists.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_get_ptr</b> and <b>_vector_get_ptr</b> are used to
+get a pointer to an element in the vector. This pointer
+actually points to the vector's internal data array. It is
+only valid as long as the user does not cause the internal
+data array to be reallocated or moved - typically this can
+happen when the user performs some operation which inserts
+more elements into the array.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked. An attempt to access an
+out-of-bounds element will result in a call to
+<b>abort(3)</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_grep</title>
+</head>
+<body>
+
+<h1 align=center>vector_grep</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:00 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_grep - produce a new vector containing elements of the old vector which match a boolean function</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+vector vector_grep (pool, vector v, int (*match_fn) (const void *));
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+This macro calls <b>match_fn(&t)</b> for each element
+<b>t</b> of vector <b>v</b>. It constructs and returns a new
+vector containing all those elements where the function
+returns true.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_grep_pool</title>
+</head>
+<body>
+
+<h1 align=center>vector_grep_pool</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:02 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_grep_pool - produce a new vector containing elements of the old vector which match a boolean function</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+vector vector_grep_pool (pool, vector v, int (*match_fn) (pool, const void *));
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+This macro calls <b>match_fn(pool, &t)</b> for each
+element <b>t</b> of vector <b>v</b>. It constructs and
+returns a new vector containing all those elements where the
+function returns true.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_insert</title>
+</head>
+<body>
+
+<h1 align=center>vector_insert</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:03 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_insert, _vector_insert, vector_insert_array - insert elements into a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_insert(v,i,obj) _vector_insert((v),(i),&(obj))
+void _vector_insert (vector, int i, const void *ptr);
+void vector_insert_array (vector v, int i, const void *ptr, int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_insert</b> inserts a single object <b>obj</b>
+before element <b>i</b>. All other elements are moved up to
+make space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_insert_array</b> inserts an array of <b>n</b>
+objects starting at address <b>ptr</b> into the vector
+before index <b>i</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_insert</title>
+</head>
+<body>
+
+<h1 align=center>vector_insert</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:04 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_insert, _vector_insert, vector_insert_array - insert elements into a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_insert(v,i,obj) _vector_insert((v),(i),&(obj))
+void _vector_insert (vector, int i, const void *ptr);
+void vector_insert_array (vector v, int i, const void *ptr, int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_insert</b> inserts a single object <b>obj</b>
+before element <b>i</b>. All other elements are moved up to
+make space.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_insert_array</b> inserts an array of <b>n</b>
+objects starting at address <b>ptr</b> into the vector
+before index <b>i</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_map</title>
+</head>
+<body>
+
+<h1 align=center>vector_map</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:05 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_map, _vector_map - apply function to each element of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_map(pool,v,map_fn,result_type) _vector_map ((pool), (v), (map_fn), sizeof (result_type))
+vector _vector_map (pool, vector v, void (*map_fn) (const void *, void *), size_t result_size);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Call <b>map_fn(&t, &r)</b> for each element <b>t</b>
+of vector <b>v</b>. The result (<b>r</b>) should have type
+<b>result_type</b> and these are concatenated to form a new
+vector which is returned.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_map_pool</title>
+</head>
+<body>
+
+<h1 align=center>vector_map_pool</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:06 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_map_pool, _vector_map_pool - apply function to each element of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_map_pool(pool,v,map_fn,result_type) _vector_map_pool ((pool), (v), (map_fn), sizeof (result_type))
+vector _vector_map_pool (pool, vector v, void (*map_fn_pool) (pool, const void *, void *), size_t result_size);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Call <b>map_fn(pool, &t, &r)</b> for each element
+<b>t</b> of vector <b>v</b>. The result (<b>r</b>) should
+have type <b>result_type</b> and these are concatenated to
+form a new vector which is returned.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_push_back</title>
+</head>
+<body>
+
+<h1 align=center>vector_push_back</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:07 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_push_back, _vector_push_back, vector_pop_back, _vector_pop_back, vector_push_front, _vector_push_front, vector_pop_front, _vector_pop_front - push and pop objects into and out of vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_push_back(v,obj) _vector_push_back((v),&(obj))
+void _vector_push_back (vector, const void *ptr);
+#define vector_pop_back(v,obj) _vector_pop_back((v),&(obj))
+void _vector_pop_back (vector, void *ptr);
+#define vector_push_front(v,obj) _vector_push_front((v),&(obj))
+void _vector_push_front (vector, const void *ptr);
+#define vector_pop_front(v,obj) _vector_pop_front((v),&(obj))
+void _vector_pop_front (vector, void *ptr);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_push_*</b> functions push objects onto
+vectors.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_pop_*</b> functions pop objects off vectors into
+local variables.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_front</b> functions push and pop objects off the
+front of a vector. This type of operation is not very
+efficient, because it involves moving all other elements of
+the vector up or down by one place.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_back</b> functions push and pop elements off the
+end of the vector, which is efficient.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Each function has two forms: a macro version and an
+underlying function.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked. You cannot pop an empty vector.
+If <b>ptr</b> is <b>NULL</b> then the popped object is
+discarded.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_push_back</title>
+</head>
+<body>
+
+<h1 align=center>vector_push_back</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:08 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_push_back, _vector_push_back, vector_pop_back, _vector_pop_back, vector_push_front, _vector_push_front, vector_pop_front, _vector_pop_front - push and pop objects into and out of vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_push_back(v,obj) _vector_push_back((v),&(obj))
+void _vector_push_back (vector, const void *ptr);
+#define vector_pop_back(v,obj) _vector_pop_back((v),&(obj))
+void _vector_pop_back (vector, void *ptr);
+#define vector_push_front(v,obj) _vector_push_front((v),&(obj))
+void _vector_push_front (vector, const void *ptr);
+#define vector_pop_front(v,obj) _vector_pop_front((v),&(obj))
+void _vector_pop_front (vector, void *ptr);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_push_*</b> functions push objects onto
+vectors.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_pop_*</b> functions pop objects off vectors into
+local variables.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_front</b> functions push and pop objects off the
+front of a vector. This type of operation is not very
+efficient, because it involves moving all other elements of
+the vector up or down by one place.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_back</b> functions push and pop elements off the
+end of the vector, which is efficient.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Each function has two forms: a macro version and an
+underlying function.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked. You cannot pop an empty vector.
+If <b>ptr</b> is <b>NULL</b> then the popped object is
+discarded.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_push_back</title>
+</head>
+<body>
+
+<h1 align=center>vector_push_back</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:09 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_push_back, _vector_push_back, vector_pop_back, _vector_pop_back, vector_push_front, _vector_push_front, vector_pop_front, _vector_pop_front - push and pop objects into and out of vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_push_back(v,obj) _vector_push_back((v),&(obj))
+void _vector_push_back (vector, const void *ptr);
+#define vector_pop_back(v,obj) _vector_pop_back((v),&(obj))
+void _vector_pop_back (vector, void *ptr);
+#define vector_push_front(v,obj) _vector_push_front((v),&(obj))
+void _vector_push_front (vector, const void *ptr);
+#define vector_pop_front(v,obj) _vector_pop_front((v),&(obj))
+void _vector_pop_front (vector, void *ptr);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_push_*</b> functions push objects onto
+vectors.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_pop_*</b> functions pop objects off vectors into
+local variables.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_front</b> functions push and pop objects off the
+front of a vector. This type of operation is not very
+efficient, because it involves moving all other elements of
+the vector up or down by one place.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_back</b> functions push and pop elements off the
+end of the vector, which is efficient.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Each function has two forms: a macro version and an
+underlying function.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked. You cannot pop an empty vector.
+If <b>ptr</b> is <b>NULL</b> then the popped object is
+discarded.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_push_back</title>
+</head>
+<body>
+
+<h1 align=center>vector_push_back</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:10 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_push_back, _vector_push_back, vector_pop_back, _vector_pop_back, vector_push_front, _vector_push_front, vector_pop_front, _vector_pop_front - push and pop objects into and out of vectors</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_push_back(v,obj) _vector_push_back((v),&(obj))
+void _vector_push_back (vector, const void *ptr);
+#define vector_pop_back(v,obj) _vector_pop_back((v),&(obj))
+void _vector_pop_back (vector, void *ptr);
+#define vector_push_front(v,obj) _vector_push_front((v),&(obj))
+void _vector_push_front (vector, const void *ptr);
+#define vector_pop_front(v,obj) _vector_pop_front((v),&(obj))
+void _vector_pop_front (vector, void *ptr);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_push_*</b> functions push objects onto
+vectors.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_pop_*</b> functions pop objects off vectors into
+local variables.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_front</b> functions push and pop objects off the
+front of a vector. This type of operation is not very
+efficient, because it involves moving all other elements of
+the vector up or down by one place.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>*_back</b> functions push and pop elements off the
+end of the vector, which is efficient.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Each function has two forms: a macro version and an
+underlying function.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked. You cannot pop an empty vector.
+If <b>ptr</b> is <b>NULL</b> then the popped object is
+discarded.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_reallocate</title>
+</head>
+<body>
+
+<h1 align=center>vector_reallocate</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:11 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_reallocate - change allocation for a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+void vector_reallocate (vector v, int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Increase the amount of space allocated to a vector. See also
+<b>vector_allocated(3)</b>. This function can be used to
+avoid the vector itself making too many calls to the
+underlying <b>prealloc(3)</b>, particularly if you know in
+advance exactly how many elements the vector will
+contain.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_replace</title>
+</head>
+<body>
+
+<h1 align=center>vector_replace</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:12 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_replace, _vector_replace, vector_replace_array - replace elements of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_replace(v,i,obj) _vector_replace((v),(i),&(obj))
+void _vector_replace (vector, int i, const void *ptr);
+void vector_replace_array (vector v, int i, const void *ptr, int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_replace</b> replaces the single element at
+<b>v[i]</b> with object <b>obj</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_replace_array</b> replaces the <b>n</b> elements
+in the vector starting at index <b>i</b> with the <b>n</b>
+elements from the array <b>ptr</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_replace</title>
+</head>
+<body>
+
+<h1 align=center>vector_replace</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:13 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_replace, _vector_replace, vector_replace_array - replace elements of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_replace(v,i,obj) _vector_replace((v),(i),&(obj))
+void _vector_replace (vector, int i, const void *ptr);
+void vector_replace_array (vector v, int i, const void *ptr, int n);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_replace</b> replaces the single element at
+<b>v[i]</b> with object <b>obj</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>vector_replace_array</b> replaces the <b>n</b> elements
+in the vector starting at index <b>i</b> with the <b>n</b>
+elements from the array <b>ptr</b>.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Array indexes are checked.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_reverse</title>
+</head>
+<body>
+
+<h1 align=center>vector_reverse</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:15 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_reverse - reverse the elements of a vector in-place</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+void vector_reverse (vector v);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Reverse the elements of a vector in-place.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_size</title>
+</head>
+<body>
+
+<h1 align=center>vector_size</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:17 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_size - return the size of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_size(v) ((v)->used)
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Return the size (ie. number of elements) in the
+vector.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_sort</title>
+</head>
+<body>
+
+<h1 align=center>vector_sort</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:19 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_sort, _vector_sort - sort a vector in-place</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+#define vector_sort(v,compare_fn) _vector_sort ((v), (int (*)(const void *,const void *)) (compare_fn))
+void _vector_sort (vector v, int (*compare_fn) (const void *, const void *));
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Sort a vector in-place, comparing elements using
+<b>compare_fn</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>vector_swap</title>
+</head>
+<body>
+
+<h1 align=center>vector_swap</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:22 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+vector_swap - swap two elements of a vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <vector.h>
+
+void vector_swap (vector v, int i, int j);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Swap elements <b>i</b> and <b>j</b> of vector
+<b>v</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>identity_matrix</title>
+</head>
+<body>
+
+<h1 align=center>identity_matrix</h1>
+<a href="#NAME">NAME</a><br>
+<a href="#SYNOPSIS">SYNOPSIS</a><br>
+<a href="#DESCRIPTION">DESCRIPTION</a><br>
+<a href="#AUTHOR">AUTHOR</a><br>
+<a href="#LICENSE">LICENSE</a><br>
+<a href="#VERSION">VERSION</a><br>
+<a href="#SEE ALSO">SEE ALSO</a><br>
+
+<hr>
+<!-- Creator : groff version 1.17.2 -->
+<!-- CreationDate: Fri May 3 14:59:23 2002 -->
+<a name="NAME"></a>
+<h2>NAME</h2>
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+identity_matrix, zero_vec, new_identity_matrix, new_zero_vec, make_identity_matrix, make_zero_vec - identity matrix and zero vector</td></table>
+<a name="SYNOPSIS"></a>
+<h2>SYNOPSIS</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<pre><b>#include <matvec.h>
+
+float identity_matrix[16];
+float zero_vec[4];
+float *new_identity_matrix (pool);
+float *new_zero_vec (pool);
+#define make_identity_matrix(m) memcpy (m, identity_matrix, sizeof(float)*16);
+#define make_zero_vec(v) memcpy (v, zero_vec, sizeof (float) * 4);
+</b></pre></td></table>
+<a name="DESCRIPTION"></a>
+<h2>DESCRIPTION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+The <b>identity_matrix</b> variable contains a read-only
+copy of the identity matrix. The <b>zero_vec</b> variable
+contains a read-only copy of the zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>new_identity_matrix</b> to allocate a new identity
+matrix variable in <b>pool</b>. Use <b>new_zero_vec</b> to
+similarly allocate a new zero vector.</td></table>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Use <b>make_identity_matrix</b> to copy the identity matrix
+over an existing matrix <b>m</b>. Use <b>make_zero_vec</b>
+to similarly copy the zero vector over an existing vector
+<b>v</b>.</td></table>
+<a name="AUTHOR"></a>
+<h2>AUTHOR</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+Richard Jones <rich@annexia.org></td></table>
+<a name="LICENSE"></a>
+<h2>LICENSE</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+GNU LGPL (see http://www.gnu.org/)</td></table>
+<a name="VERSION"></a>
+<h2>VERSION</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+c2lib-1.2.13</td></table>
+<a name="SEE ALSO"></a>
+<h2>SEE ALSO</h2>
+
+<table width="100%" border=0 rules="none" frame="void"
+ cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%"></td><td width="90%">
+<b>new_matrix(3)</b>, <b>new_vec(3)</b>.</td></table>
+<hr>
+</body>
+</html>
--- /dev/null
+/* A hash class.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: hash.c,v 1.4 2002/11/26 19:47:29 rich Exp $
+ */
+
+#include "config.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <pstring.h>
+#include <vector.h>
+#include <hash.h>
+
+struct hash
+{
+ pool pool;
+ size_t key_size;
+ size_t value_size;
+ vector buckets;
+};
+
+struct sash
+{
+ pool pool;
+ vector buckets;
+};
+
+struct shash
+{
+ pool pool;
+ size_t value_size;
+ vector buckets;
+};
+
+#define HASH_NR_BUCKETS 32
+
+/* This is the hashing function -- the same one as used by Perl. */
+static inline unsigned
+HASH (const void *key, size_t key_size, int nr_buckets)
+{
+ unsigned h = 0;
+ const char *s = (const char *) key;
+
+ while (key_size--)
+ h = h * 33 + *s++;
+
+ return h & (nr_buckets - 1);
+}
+
+/*----- HASHes -----*/
+
+struct hash_bucket_entry
+{
+ void *key;
+ void *value;
+};
+
+hash
+_hash_new (pool pool, size_t key_size, size_t value_size)
+{
+ hash h;
+ vector null = 0;
+
+ h = pmalloc (pool, sizeof *h);
+ h->pool = pool;
+ h->key_size = key_size;
+ h->value_size = value_size;
+ h->buckets = new_vector (pool, sizeof (vector));
+ vector_fill (h->buckets, null, HASH_NR_BUCKETS);
+
+ return h;
+}
+
+/* NB. This only copies the hash, NOT the structures or whatever
+ * which might be pointed to by keys/values in the hash. Beware.
+ */
+hash
+copy_hash (pool pool, hash h)
+{
+ hash new_h;
+ int b, i;
+
+ new_h = pmalloc (pool, sizeof *new_h);
+ new_h->pool = pool;
+ new_h->key_size = h->key_size;
+ new_h->value_size = h->value_size;
+ new_h->buckets = copy_vector (pool, h->buckets);
+
+ /* Copy the buckets. */
+ for (b = 0; b < vector_size (new_h->buckets); ++b)
+ {
+ vector v;
+
+ vector_get (new_h->buckets, b, v);
+
+ if (v)
+ {
+ v = copy_vector (pool, v);
+ vector_replace (new_h->buckets, b, v);
+
+ /* Copy the keys/values in this vector. */
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ struct hash_bucket_entry entry;
+
+ vector_get (v, i, entry);
+ entry.key = pmemdup (pool, entry.key, h->key_size);
+ entry.value = pmemdup (pool, entry.value, h->value_size);
+ vector_replace (v, i, entry);
+ }
+ }
+ }
+
+ return new_h;
+}
+
+int
+_hash_get (hash h, const void *key, void *value)
+{
+ const void *ptr;
+
+ ptr = _hash_get_ptr (h, key);
+ if (ptr == 0) return 0;
+
+ if (value) memcpy (value, ptr, h->value_size);
+ return 1;
+}
+
+const void *
+_hash_get_ptr (hash h, const void *key)
+{
+ int b, i;
+ vector bucket;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, h->key_size, vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ if (bucket == 0)
+ return 0;
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ struct hash_bucket_entry entry;
+
+ vector_get (bucket, i, entry);
+ if (memcmp (entry.key, key, h->key_size) == 0)
+ return entry.value;
+ }
+
+ return 0;
+}
+
+int
+_hash_insert (hash h, const void *key, const void *value)
+{
+ int b, i;
+ vector bucket;
+ struct hash_bucket_entry entry;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, h->key_size, vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ /* If there is no bucket there, we have to allocate a fresh vector. */
+ if (bucket == 0)
+ {
+ bucket = new_vector (h->pool, struct hash_bucket_entry);
+ vector_replace (h->buckets, b, bucket);
+ }
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ vector_get (bucket, i, entry);
+ if (memcmp (entry.key, key, h->key_size) == 0)
+ {
+ memcpy (entry.value, value, h->value_size);
+ /*entry.value = pmemdup (h->pool, value, h->value_size);*/
+
+ /* Replace this entry. */
+ vector_replace (bucket, i, entry);
+
+ return 1;
+ }
+ }
+
+ /* Append to this bucket. */
+ entry.key = pmemdup (h->pool, key, h->key_size);
+ entry.value = pmemdup (h->pool, value, h->value_size);
+
+ vector_push_back (bucket, entry);
+ return 0;
+}
+
+int
+_hash_erase (hash h, const void *key)
+{
+ int b, i;
+ vector bucket;
+ struct hash_bucket_entry entry;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, h->key_size, vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ if (bucket == 0) return 0;
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ vector_get (bucket, i, entry);
+ if (memcmp (entry.key, key, h->key_size) == 0)
+ {
+ /* Remove this entry. */
+ vector_erase (bucket, i);
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+inline vector
+hash_keys_in_pool (hash h, pool p)
+{
+ int i, j;
+ vector bucket, keys;
+ struct hash_bucket_entry entry;
+
+ keys = _vector_new (p, h->key_size);
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+
+ if (bucket)
+ for (j = 0; j < vector_size (bucket); ++j)
+ {
+ vector_get (bucket, j, entry);
+ _vector_push_back (keys, entry.key);
+ }
+ }
+
+ return keys;
+}
+
+vector
+hash_keys (hash h)
+{
+ return hash_keys_in_pool (h, h->pool);
+}
+
+inline vector
+hash_values_in_pool (hash h, pool p)
+{
+ int i, j;
+ vector bucket, values;
+ struct hash_bucket_entry entry;
+
+ values = _vector_new (p, h->value_size);
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+
+ if (bucket)
+ for (j = 0; j < vector_size (bucket); ++j)
+ {
+ vector_get (bucket, j, entry);
+ _vector_push_back (values, entry.value);
+ }
+ }
+
+ return values;
+}
+
+vector
+hash_values (hash h)
+{
+ return hash_values_in_pool (h, h->pool);
+}
+
+int
+hash_size (hash h)
+{
+ vector bucket;
+ int n = 0, i;
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+ n += bucket ? vector_size (bucket) : 0;
+ }
+
+ return n;
+}
+
+int
+hash_get_buckets_used (hash h)
+{
+ vector bucket;
+ int n = 0, i;
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+ n += bucket ? 1 : 0;
+ }
+
+ return n;
+}
+
+int
+hash_get_buckets_allocated (hash h)
+{
+ return vector_size (h->buckets);
+}
+
+void
+hash_set_buckets_allocated (hash h, int new_size)
+{
+ vector null = 0;
+
+ /* The user has been warned not to call this after elements have been
+ * inserted into the hash, and to make NEW_SIZE a power of 2.
+ */
+ if (vector_size (h->buckets) > new_size)
+ vector_erase_range (h->buckets, new_size, vector_size (h->buckets));
+ else if (vector_size (h->buckets) < new_size)
+ vector_fill (h->buckets, null, new_size - vector_size (h->buckets));
+}
+
+/*----- SASHes -----*/
+
+struct sash_bucket_entry
+{
+ char *key;
+ char *value;
+ int value_allocated;
+};
+
+sash
+new_sash (pool pool)
+{
+ sash h;
+ vector null = 0;
+
+ h = pmalloc (pool, sizeof *h);
+ h->pool = pool;
+ h->buckets = new_vector (pool, sizeof (vector));
+ vector_fill (h->buckets, null, HASH_NR_BUCKETS);
+
+ return h;
+}
+
+/* NB. Unlike copy_hash, this does copy the strings into the new
+ * pool. So a copy_sash is really a deep copy of the string hash and the
+ * strings.
+ */
+sash
+copy_sash (pool pool, sash h)
+{
+ sash new_h;
+ int b, i;
+
+ new_h = pmalloc (pool, sizeof *new_h);
+ new_h->pool = pool;
+ new_h->buckets = copy_vector (pool, h->buckets);
+
+ /* Copy the buckets. */
+ for (b = 0; b < vector_size (new_h->buckets); ++b)
+ {
+ vector v;
+
+ vector_get (new_h->buckets, b, v);
+
+ if (v)
+ {
+ v = copy_vector (pool, v);
+ vector_replace (new_h->buckets, b, v);
+
+ /* Copy the string keys/values in this vector. */
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ struct sash_bucket_entry entry;
+
+ vector_get (v, i, entry);
+ entry.key = pstrdup (pool, entry.key);
+ entry.value = pstrdup (pool, entry.value);
+ vector_replace (v, i, entry);
+ }
+ }
+ }
+
+ return new_h;
+}
+
+int
+_sash_get (sash h, const char *key, const char **ptr)
+{
+ int b, i;
+ vector bucket;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, strlen (key), vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ if (bucket == 0)
+ {
+ if (ptr) *ptr = 0;
+ return 0;
+ }
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ struct sash_bucket_entry entry;
+
+ vector_get (bucket, i, entry);
+ if (strcmp (entry.key, key) == 0)
+ {
+ if (ptr) *ptr = entry.value;
+ return 1;
+ }
+ }
+
+ if (ptr) *ptr = 0;
+ return 0;
+}
+
+int
+sash_insert (sash h, const char *key, const char *value)
+{
+ int b, i, len = strlen (value);
+ vector bucket;
+ struct sash_bucket_entry entry;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, strlen (key), vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ /* If there is no bucket there, we have to allocate a fresh vector. */
+ if (bucket == 0)
+ {
+ bucket = new_vector (h->pool, struct sash_bucket_entry);
+ vector_replace (h->buckets, b, bucket);
+ }
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ vector_get (bucket, i, entry);
+ if (strcmp (entry.key, key) == 0)
+ {
+ /* To avoid unnecessarily allocating more memory, we try to
+ * be clever here. If the existing allocation is large enough
+ * to store the new string, use it. Otherwise reallocate it
+ * to make it bigger.
+ */
+ if (len < entry.value_allocated)
+ memcpy (entry.value, value, len + 1);
+ else
+ {
+ entry.value = prealloc (h->pool, entry.value, len + 1);
+ memcpy (entry.value, value, len + 1);
+ entry.value_allocated = len + 1;
+ }
+
+ /* Replace this entry. */
+ vector_replace (bucket, i, entry);
+
+ return 1;
+ }
+ }
+
+ /* Append to this bucket. */
+ entry.key = pstrdup (h->pool, key);
+ entry.value = pstrdup (h->pool, value);
+ entry.value_allocated = len + 1;
+
+ vector_push_back (bucket, entry);
+ return 0;
+}
+
+int
+sash_erase (sash h, const char *key)
+{
+ int b, i;
+ vector bucket;
+ struct sash_bucket_entry entry;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, strlen (key), vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ if (bucket == 0) return 0;
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ vector_get (bucket, i, entry);
+ if (strcmp (entry.key, key) == 0)
+ {
+ /* Remove this entry. */
+ vector_erase (bucket, i);
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+inline vector
+sash_keys_in_pool (sash h, pool p)
+{
+ int i, j;
+ vector bucket, keys;
+ struct sash_bucket_entry entry;
+
+ keys = new_vector (p, char *);
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+
+ if (bucket)
+ for (j = 0; j < vector_size (bucket); ++j)
+ {
+ char *key;
+
+ vector_get (bucket, j, entry);
+ key = pstrdup (p, entry.key);
+ vector_push_back (keys, key);
+ }
+ }
+
+ return keys;
+}
+
+vector
+sash_keys (sash h)
+{
+ return sash_keys_in_pool (h, h->pool);
+}
+
+inline vector
+sash_values_in_pool (sash h, pool p)
+{
+ int i, j;
+ vector bucket, values;
+ struct sash_bucket_entry entry;
+
+ values = new_vector (p, char *);
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+
+ if (bucket)
+ for (j = 0; j < vector_size (bucket); ++j)
+ {
+ char *value;
+
+ vector_get (bucket, j, entry);
+ value = pstrdup (p, entry.value);
+ vector_push_back (values, value);
+ }
+ }
+
+ return values;
+}
+
+vector
+sash_values (sash h)
+{
+ return sash_values_in_pool (h, h->pool);
+}
+
+int
+sash_size (sash h)
+{
+ vector bucket;
+ int n = 0, i;
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+ n += bucket ? vector_size (bucket) : 0;
+ }
+
+ return n;
+}
+
+int
+sash_get_buckets_used (sash h)
+{
+ vector bucket;
+ int n = 0, i;
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+ n += bucket ? 1 : 0;
+ }
+
+ return n;
+}
+
+int
+sash_get_buckets_allocated (sash h)
+{
+ return vector_size (h->buckets);
+}
+
+void
+sash_set_buckets_allocated (sash h, int new_size)
+{
+ vector null = 0;
+
+ /* The user has been warned not to call this after elements have been
+ * inserted into the sash, and to make NEW_SIZE a power of 2.
+ */
+ if (vector_size (h->buckets) > new_size)
+ vector_erase_range (h->buckets, new_size, vector_size (h->buckets));
+ else if (vector_size (h->buckets) < new_size)
+ vector_fill (h->buckets, null, new_size - vector_size (h->buckets));
+}
+
+/*----- SHASHes -----*/
+
+struct shash_bucket_entry
+{
+ char *key;
+ void *value;
+};
+
+shash
+_shash_new (pool pool, size_t value_size)
+{
+ shash h;
+ vector null = 0;
+
+ h = pmalloc (pool, sizeof *h);
+ h->pool = pool;
+ h->value_size = value_size;
+ h->buckets = new_vector (pool, sizeof (vector));
+ vector_fill (h->buckets, null, HASH_NR_BUCKETS);
+
+ return h;
+}
+
+/* NB. Unlike copy_hash, this does copy the strings into the new
+ * pool. So a copy_shash is really a deep copy of the shash and the
+ * strings.
+ */
+shash
+copy_shash (pool pool, shash h)
+{
+ shash new_h;
+ int b, i;
+
+ new_h = pmalloc (pool, sizeof *new_h);
+ new_h->pool = pool;
+ new_h->value_size = h->value_size;
+ new_h->buckets = copy_vector (pool, h->buckets);
+
+ /* Copy the buckets. */
+ for (b = 0; b < vector_size (new_h->buckets); ++b)
+ {
+ vector v;
+
+ vector_get (new_h->buckets, b, v);
+
+ if (v)
+ {
+ v = copy_vector (pool, v);
+ vector_replace (new_h->buckets, b, v);
+
+ /* Copy the string keys in this vector. */
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ struct shash_bucket_entry entry;
+
+ vector_get (v, i, entry);
+ entry.key = pstrdup (pool, entry.key);
+ entry.value = pmemdup (pool, entry.value, h->value_size);
+ vector_replace (v, i, entry);
+ }
+ }
+ }
+
+ return new_h;
+}
+
+int
+_shash_get (shash h, const char *key, void *value)
+{
+ const void *ptr;
+
+ ptr = _shash_get_ptr (h, key);
+ if (ptr == 0) return 0;
+
+ if (value) memcpy (value, ptr, h->value_size);
+ return 1;
+}
+
+const void *
+_shash_get_ptr (shash h, const char *key)
+{
+ int b, i;
+ vector bucket;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, strlen (key), vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ if (bucket == 0)
+ return 0;
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ struct shash_bucket_entry entry;
+
+ vector_get (bucket, i, entry);
+ if (strcmp (entry.key, key) == 0)
+ return entry.value;
+ }
+
+ return 0;
+}
+
+int
+_shash_insert (shash h, const char *key, const void *value)
+{
+ int b, i;
+ vector bucket;
+ struct shash_bucket_entry entry;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, strlen (key), vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ /* If there is no bucket there, we have to allocate a fresh vector. */
+ if (bucket == 0)
+ {
+ bucket = new_vector (h->pool, struct shash_bucket_entry);
+ vector_replace (h->buckets, b, bucket);
+ }
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ vector_get (bucket, i, entry);
+ if (strcmp (entry.key, key) == 0)
+ {
+ memcpy (entry.value, value, h->value_size);
+ /*entry.value = pmemdup (h->pool, value, h->value_size);*/
+
+ /* Replace this entry. */
+ vector_replace (bucket, i, entry);
+
+ return 1;
+ }
+ }
+
+ /* Append to this bucket. */
+ entry.key = pstrdup (h->pool, key);
+ entry.value = pmemdup (h->pool, value, h->value_size);
+
+ vector_push_back (bucket, entry);
+ return 0;
+}
+
+int
+shash_erase (shash h, const char *key)
+{
+ int b, i;
+ vector bucket;
+ struct shash_bucket_entry entry;
+
+ /* Find the appropriate bucket. */
+ b = HASH (key, strlen (key), vector_size (h->buckets));
+ vector_get (h->buckets, b, bucket);
+
+ if (bucket == 0) return 0;
+
+ /* Search this bucket linearly. */
+ for (i = 0; i < vector_size (bucket); ++i)
+ {
+ vector_get (bucket, i, entry);
+ if (strcmp (entry.key, key) == 0)
+ {
+ /* Remove this entry. */
+ vector_erase (bucket, i);
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+inline vector
+shash_keys_in_pool (shash h, pool p)
+{
+ int i, j;
+ vector bucket, keys;
+ struct shash_bucket_entry entry;
+
+ keys = new_vector (p, char *);
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+
+ if (bucket)
+ for (j = 0; j < vector_size (bucket); ++j)
+ {
+ char *key;
+
+ vector_get (bucket, j, entry);
+ key = pstrdup (p, entry.key);
+ vector_push_back (keys, key);
+ }
+ }
+
+ return keys;
+}
+
+vector
+shash_keys (shash h)
+{
+ return shash_keys_in_pool (h, h->pool);
+}
+
+inline vector
+shash_values_in_pool (shash h, pool p)
+{
+ int i, j;
+ vector bucket, values;
+ struct shash_bucket_entry entry;
+
+ values = _vector_new (p, h->value_size);
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+
+ if (bucket)
+ for (j = 0; j < vector_size (bucket); ++j)
+ {
+ vector_get (bucket, j, entry);
+ _vector_push_back (values, entry.value);
+ }
+ }
+
+ return values;
+}
+
+vector
+shash_values (shash h)
+{
+ return shash_values_in_pool (h, h->pool);
+}
+
+int
+shash_size (shash h)
+{
+ vector bucket;
+ int n = 0, i;
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+ n += bucket ? vector_size (bucket) : 0;
+ }
+
+ return n;
+}
+
+int
+shash_get_buckets_used (shash h)
+{
+ vector bucket;
+ int n = 0, i;
+
+ for (i = 0; i < vector_size (h->buckets); ++i)
+ {
+ vector_get (h->buckets, i, bucket);
+ n += bucket ? 1 : 0;
+ }
+
+ return n;
+}
+
+int
+shash_get_buckets_allocated (shash h)
+{
+ return vector_size (h->buckets);
+}
+
+void
+shash_set_buckets_allocated (shash h, int new_size)
+{
+ vector null = 0;
+
+ /* The user has been warned not to call this after elements have been
+ * inserted into the shash, and to make NEW_SIZE a power of 2.
+ */
+ if (vector_size (h->buckets) > new_size)
+ vector_erase_range (h->buckets, new_size, vector_size (h->buckets));
+ else if (vector_size (h->buckets) < new_size)
+ vector_fill (h->buckets, null, new_size - vector_size (h->buckets));
+}
--- /dev/null
+/* Generalized hash and string hash (sash) classes.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: hash.h,v 1.6 2002/11/26 19:47:30 rich Exp $
+ */
+
+#ifndef HASH_H
+#define HASH_H
+
+#include <vector.h>
+
+/* Note, hash and sash are identical but for the fact that
+ * hash maps fixed sized keys to values (eg. int -> int or
+ * int -> struct) and sash maps nul-terminated ASCII strings
+ * to nul-terminated ASCII strings (ie. string -> string ONLY).
+ * shash maps nul-terminated ASCII strings to anything else.
+ */
+
+struct hash;
+typedef struct hash *hash;
+
+struct sash;
+typedef struct sash *sash;
+
+struct shash;
+typedef struct shash *shash;
+
+/* Function: new_hash - allocate a new hash
+ * Function: _hash_new
+ *
+ * Allocate a new hash in @code{pool} mapping
+ * @code{key_type} to @code{value_type}. You can map both
+ * simple types like @code{int} and also aggregate types
+ * like structures and unions. However, beware of aggregate
+ * types that might contain 'holes' because of alignment --
+ * such types will probably not work as you expect, particularly
+ * if used as keys.
+ *
+ * If you wish to have
+ * a hash which maps strings to something, then calling
+ * @code{new_hash(pool, char *, char *)} (for example) will not do what
+ * you expect. You are better to use either a sash (string to string hash)
+ * or a shash (string to anything hash) instead (see
+ * @ref{new_sash(3)} and @ref{new_shash(3)}).
+ */
+#define new_hash(pool,key_type,value_type) _hash_new ((pool), sizeof (key_type), sizeof (value_type))
+extern hash _hash_new (pool, size_t key_size, size_t value_size);
+
+/* Function: copy_hash - copy a hash
+ *
+ * Copy a hash into a new pool. This function copies the keys
+ * and values, but if keys and values are pointers, then it does
+ * not perform a 'deep' copy.
+ */
+extern hash copy_hash (pool, hash);
+
+/* Function: hash_get - look up in a hash
+ * Function: _hash_get
+ * Function: hash_get_ptr
+ * Function: _hash_get_ptr
+ * Function: hash_exists
+ *
+ * Get the @code{value} associated with key @code{key} and return true.
+ * If there is no @code{value} associated with @code{key}, this returns
+ * false and @code{value} is left unchanged.
+ *
+ * The @code{*_ptr} variants return a pointer rather than copying
+ * out the entire value object. The pointer is typically only
+ * valid for a short period of time. Particularly if you insert
+ * or remove elements from the hash, this pointer may become
+ * invalid.
+ *
+ * @code{hash_exists} simply tests whether or not @code{key} exists
+ * in the hash. If so, it returns true, otherwise false.
+ */
+#define hash_get(h,key,value) _hash_get ((h), &(key), &(value))
+extern int _hash_get (hash, const void *key, void *value);
+#define hash_get_ptr(h,key,ptr) ((ptr) = ((typeof (ptr))_hash_get_ptr ((h), &(key))))
+extern const void *_hash_get_ptr (hash, const void *key);
+#define hash_exists(h,key) (_hash_get_ptr ((h), &(key)) ? 1 : 0)
+
+/* Function: hash_insert - insert a (key, value) pair into a hash
+ * Function: _hash_insert
+ *
+ * Insert an element (@code{key}, @code{value}) into the hash.
+ * If @code{key} already
+ * exists in the hash, then the existing value is replaced by
+ * @code{value}
+ * and the function returns true. If there was no previous @code{key}
+ * in the hash then this function returns false.
+ */
+#define hash_insert(h,key,value) _hash_insert((h),&(key),&(value))
+extern int _hash_insert (hash, const void *key, const void *value);
+
+/* Function: hash_erase - erase a key from a hash
+ * Function: _hash_erase
+ *
+ * Erase @code{key} from the hash. If an element was erased,
+ * this returns true, else this returns false.
+ */
+#define hash_erase(h,key) _hash_erase((h),&(key))
+extern int _hash_erase (hash, const void *key);
+
+/* Function: hash_keys - return a vector of the keys or values in a hash
+ * Function: hash_keys_in_pool
+ * Function: hash_values
+ * Function: hash_values_in_pool
+ *
+ * Return a vector containing all the keys or values of hash. The
+ * @code{*_in_pool} variants allow you to allocate the vector in
+ * another pool (the default is to allocate the vector in the same
+ * pool as the hash).
+ */
+extern vector hash_keys (hash);
+extern vector hash_keys_in_pool (hash, pool);
+extern vector hash_values (hash);
+extern vector hash_values_in_pool (hash, pool);
+
+/* Function: hash_size - return the number of (key, value) pairs in a hash
+ *
+ * Count the number of (key, value) pairs in the hash.
+ */
+extern int hash_size (hash);
+
+/* Function: hash_get_buckets_used - return the number of buckets in a hash
+ * Function: hash_get_buckets_allocated
+ *
+ * Return the number of hash buckets used and allocated. The number of
+ * buckets allocated is always a power of 2. See also
+ * @ref{hash_set_buckets_allocated} to change the number used
+ * in the hash.
+ */
+extern int hash_get_buckets_used (hash);
+extern int hash_get_buckets_allocated (hash);
+
+/* Function: hash_set_buckets_allocated - set the number of buckets
+ *
+ * Set the number of buckets allocated. You may ONLY do this when you
+ * have just created the hash and before you have inserted any elements.
+ * Otherwise the results are undefined (and probably bad). The number
+ * of buckets MUST be a power of 2.
+ */
+extern void hash_set_buckets_allocated (hash, int);
+
+/* Function: new_sash - allocate a new sash (string hash)
+ *
+ * Allocate a new sash in @code{pool} mapping
+ * strings to strings.
+ *
+ * Use a string hash in preference to a hash of
+ * @code{char *} -> @code{char *} which will probably not
+ * quite work as you expect.
+ */
+extern sash new_sash (pool);
+
+/* Function: copy_sash - copy a sash
+ *
+ * Copy a sash into a new pool. This function copies the keys
+ * and values, but if keys and values are pointers, then it does
+ * not perform a 'deep' copy.
+ */
+extern sash copy_sash (pool, sash);
+
+/* Function: sash_get - look up in a sash
+ * Function: _sash_get
+ * Function: sash_exists
+ *
+ * Get the @code{value} associated with key @code{key} and return true.
+ * If there is no @code{value} associated with @code{key}, this returns
+ * false and @code{value} is left unchanged.
+ *
+ * @code{sash_exists} simply tests whether or not @code{key} exists
+ * in the sash. If so, it returns true, otherwise false.
+ */
+#define sash_get(sash,key,value) _sash_get((sash),(key),&(value))
+extern int _sash_get (sash, const char *key, const char **ptr);
+#define sash_exists(sash,key) _sash_get ((sash), (key), 0)
+
+/* Function: sash_insert - insert a (key, value) pair into a sash
+ *
+ * Insert an element (@code{key}, @code{value}) into the sash.
+ * If @code{key} already
+ * exists in the sash, then the existing value is replaced by
+ * @code{value}
+ * and the function returns true. If there was no previous @code{key}
+ * in the sash then this function returns false.
+ */
+extern int sash_insert (sash, const char *key, const char *value);
+
+/* Function: sash_erase - erase a key from a sash
+ *
+ * Erase @code{key} from the sash. If an element was erased,
+ * this returns true, else this returns false.
+ */
+extern int sash_erase (sash, const char *key);
+
+/* Function: sash_keys - return a vector of the keys or values in a sash
+ * Function: sash_keys_in_pool
+ * Function: sash_values
+ * Function: sash_values_in_pool
+ *
+ * Return a vector containing all the keys or values of sash. The
+ * @code{*_in_pool} variants allow you to allocate the vector in
+ * another pool (the default is to allocate the vector in the same
+ * pool as the sash).
+ */
+extern vector sash_keys (sash);
+extern vector sash_keys_in_pool (sash, pool);
+extern vector sash_values (sash);
+extern vector sash_values_in_pool (sash, pool);
+
+/* Function: sash_size - return the number of (key, value) pairs in a sash
+ *
+ * Count the number of (key, value) pairs in the sash.
+ */
+extern int sash_size (sash);
+
+/* Function: sash_get_buckets_used - return the number of buckets in a sash
+ * Function: sash_get_buckets_allocated
+ *
+ * Return the number of sash buckets used and allocated. The number of
+ * buckets allocated is always a power of 2. See also
+ * @ref{sash_set_buckets_allocated} to change the number used
+ * in the sash.
+ */
+extern int sash_get_buckets_used (sash);
+extern int sash_get_buckets_allocated (sash);
+
+/* Function: sash_set_buckets_allocated - set the number of buckets
+ *
+ * Set the number of buckets allocated. You may ONLY do this when you
+ * have just created the sash and before you have inserted any elements.
+ * Otherwise the results are undefined (and probably bad). The number
+ * of buckets MUST be a power of 2.
+ */
+extern void sash_set_buckets_allocated (sash, int);
+
+/* Function: new_shash - allocate a new shash (string -> something hash)
+ *
+ * Allocate a new shash in @code{pool} mapping
+ * strings to strings.
+ *
+ * Use a shash in preference to a hash of
+ * @code{char *} -> something which will probably not
+ * quite work as you expect.
+ */
+#define new_shash(pool,value_type) _shash_new ((pool), sizeof (value_type))
+extern shash _shash_new (pool, size_t value_size);
+
+/* Function: copy_shash - copy a shash
+ *
+ * Copy a shash into a new pool. This function copies the keys
+ * and values, but if keys and values are pointers, then it does
+ * not perform a 'deep' copy.
+ */
+extern shash copy_shash (pool, shash);
+
+/* Function: shash_get - look up in a shash
+ * Function: _shash_get
+ * Function: shash_get_ptr
+ * Function: _shash_get_ptr
+ * Function: shash_exists
+ *
+ * Get the @code{value} associated with key @code{key} and return true.
+ * If there is no @code{value} associated with @code{key}, this returns
+ * false and @code{value} is left unchanged.
+ *
+ * The @code{*_ptr} variants return a pointer rather than copying
+ * out the entire value object. The pointer is typically only
+ * valid for a short period of time. Particularly if you insert
+ * or remove elements from the shash, this pointer may become
+ * invalid.
+ *
+ * @code{shash_exists} simply tests whether or not @code{key} exists
+ * in the shash. If so, it returns true, otherwise false.
+ */
+#define shash_get(shash,key,value) _shash_get((shash),(key),&(value))
+extern int _shash_get (shash, const char *key, void *value);
+#define shash_get_ptr(h,key,ptr) ((ptr) = ((typeof (ptr))_shash_get_ptr ((h),(key))))
+extern const void *_shash_get_ptr (shash, const char *key);
+#define shash_exists(shash,key) (_shash_get_ptr ((shash), (key)) ? 1 : 0)
+
+/* Function: shash_insert - insert a (key, value) pair into a shash
+ * Function: _shash_insert
+ *
+ * Insert an element (@code{key}, @code{value}) into the shash.
+ * If @code{key} already
+ * exists in the shash, then the existing value is replaced by
+ * @code{value}
+ * and the function returns true. If there was no previous @code{key}
+ * in the shash then this function returns false.
+ */
+#define shash_insert(h,key,value) _shash_insert((h),(key),&(value))
+extern int _shash_insert (shash, const char *key, const void *value);
+
+/* Function: shash_erase - erase a key from a shash
+ *
+ * Erase @code{key} from the shash. If an element was erased,
+ * this returns true, else this returns false.
+ */
+extern int shash_erase (shash, const char *key);
+
+/* Function: shash_keys - return a vector of the keys or values in a shash
+ * Function: shash_keys_in_pool
+ * Function: shash_values
+ * Function: shash_values_in_pool
+ *
+ * Return a vector containing all the keys or values of shash. The
+ * @code{*_in_pool} variants allow you to allocate the vector in
+ * another pool (the default is to allocate the vector in the same
+ * pool as the shash).
+ */
+extern vector shash_keys (shash);
+extern vector shash_keys_in_pool (shash, pool);
+extern vector shash_values (shash);
+extern vector shash_values_in_pool (shash, pool);
+
+/* Function: shash_size - return the number of (key, value) pairs in a shash
+ *
+ * Count the number of (key, value) pairs in the shash.
+ */
+extern int shash_size (shash);
+
+/* Function: shash_get_buckets_used - return the number of buckets in a shash
+ * Function: shash_get_buckets_allocated
+ *
+ * Return the number of shash buckets used and allocated. The number of
+ * buckets allocated is always a power of 2. See also
+ * @ref{shash_set_buckets_allocated} to change the number used
+ * in the shash.
+ */
+extern int shash_get_buckets_used (shash);
+extern int shash_get_buckets_allocated (shash);
+
+/* Function: shash_set_buckets_allocated - set the number of buckets
+ *
+ * Set the number of buckets allocated. You may ONLY do this when you
+ * have just created the shash and before you have inserted any elements.
+ * Otherwise the results are undefined (and probably bad). The number
+ * of buckets MUST be a power of 2.
+ */
+extern void shash_set_buckets_allocated (shash, int);
+
+#endif /* HASH_H */
--- /dev/null
+/* Matrix and vector arithmetic.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: matvec.c,v 1.5 2002/05/04 11:54:23 rich Exp $
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "matvec.h"
+
+float identity_matrix[16] = {
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+};
+
+float zero_vec[4] = { 0, 0, 0, 1 };
+
+float *
+new_identity_matrix (pool pool)
+{
+ float *m = new_matrix (pool);
+ make_identity_matrix (m);
+ return m;
+}
+
+float *
+new_zero_vec (pool pool)
+{
+ float *v = new_vec (pool);
+ make_zero_vec (v);
+ return v;
+}
+
+/* This code is taken from Mesa 3.0. I have exchanged degrees for radians. */
+void
+make_rotation_matrix (float angle,
+ float x, float y, float z,
+ float *m)
+{
+ /* This function contributed by Erich Boleyn (erich@uruk.org) */
+ float mag, s, c;
+ float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
+
+ s = sin(angle);
+ c = cos(angle);
+
+ mag = sqrt ( x*x + y*y + z*z );
+
+ if (mag == 0.0) {
+ /* generate an identity matrix and return */
+ make_identity_matrix (m);
+ return;
+ }
+
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+#define M(row,col) m[col*4+row]
+
+ /*
+ * Arbitrary axis rotation matrix.
+ *
+ * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
+ * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation
+ * (which is about the X-axis), and the two composite transforms
+ * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
+ * from the arbitrary axis to the X-axis then back. They are
+ * all elementary rotations.
+ *
+ * Rz' is a rotation about the Z-axis, to bring the axis vector
+ * into the x-z plane. Then Ry' is applied, rotating about the
+ * Y-axis to bring the axis vector parallel with the X-axis. The
+ * rotation about the X-axis is then performed. Ry and Rz are
+ * simply the respective inverse transforms to bring the arbitrary
+ * axis back to it's original orientation. The first transforms
+ * Rz' and Ry' are considered inverses, since the data from the
+ * arbitrary axis gives you info on how to get to it, not how
+ * to get away from it, and an inverse must be applied.
+ *
+ * The basic calculation used is to recognize that the arbitrary
+ * axis vector (x, y, z), since it is of unit length, actually
+ * represents the sines and cosines of the angles to rotate the
+ * X-axis to the same orientation, with theta being the angle about
+ * Z and phi the angle about Y (in the order described above)
+ * as follows:
+ *
+ * cos ( theta ) = x / sqrt ( 1 - z^2 )
+ * sin ( theta ) = y / sqrt ( 1 - z^2 )
+ *
+ * cos ( phi ) = sqrt ( 1 - z^2 )
+ * sin ( phi ) = z
+ *
+ * Note that cos ( phi ) can further be inserted to the above
+ * formulas:
+ *
+ * cos ( theta ) = x / cos ( phi )
+ * sin ( theta ) = y / sin ( phi )
+ *
+ * ...etc. Because of those relations and the standard trigonometric
+ * relations, it is pssible to reduce the transforms down to what
+ * is used below. It may be that any primary axis chosen will give the
+ * same results (modulo a sign convention) using thie method.
+ *
+ * Particularly nice is to notice that all divisions that might
+ * have caused trouble when parallel to certain planes or
+ * axis go away with care paid to reducing the expressions.
+ * After checking, it does perform correctly under all cases, since
+ * in all the cases of division where the denominator would have
+ * been zero, the numerator would have been zero as well, giving
+ * the expected result.
+ */
+
+ xx = x * x;
+ yy = y * y;
+ zz = z * z;
+ xy = x * y;
+ yz = y * z;
+ zx = z * x;
+ xs = x * s;
+ ys = y * s;
+ zs = z * s;
+ one_c = 1.0F - c;
+
+ M(0,0) = (one_c * xx) + c;
+ M(0,1) = (one_c * xy) - zs;
+ M(0,2) = (one_c * zx) + ys;
+ M(0,3) = 0.0F;
+
+ M(1,0) = (one_c * xy) + zs;
+ M(1,1) = (one_c * yy) + c;
+ M(1,2) = (one_c * yz) - xs;
+ M(1,3) = 0.0F;
+
+ M(2,0) = (one_c * zx) - ys;
+ M(2,1) = (one_c * yz) + xs;
+ M(2,2) = (one_c * zz) + c;
+ M(2,3) = 0.0F;
+
+ M(3,0) = 0.0F;
+ M(3,1) = 0.0F;
+ M(3,2) = 0.0F;
+ M(3,3) = 1.0F;
+
+#undef M
+}
+
+void
+make_translation_matrix (float x, float y, float z, float *m)
+{
+ make_identity_matrix (m);
+ m[12] = x;
+ m[13] = y;
+ m[14] = z;
+}
+
+void
+make_scaling_matrix (float x, float y, float z, float *m)
+{
+ make_identity_matrix (m);
+ m[0] = x;
+ m[5] = y;
+ m[10] = z;
+}
+
+/* The next two functions are from the matrix FAQ by <hexapod@netcom.com>, see:
+ * http://www.flipcode.com/documents/matrfaq.html
+ */
+
+/* Quickly convert 3 Euler angles to a rotation matrix. */
+void
+matrix_euler_to_rotation (float angle_x, float angle_y, float angle_z,
+ float *mat)
+{
+ float A = cos(angle_x);
+ float B = sin(angle_x);
+ float C = cos(angle_y);
+ float D = sin(angle_y);
+ float E = cos(angle_z);
+ float F = sin(angle_z);
+
+ float AD = A * D;
+ float BD = B * D;
+
+ mat[0] = C * E;
+ mat[4] = -C * F;
+ mat[8] = -D;
+ mat[1] = -BD * E + A * F;
+ mat[5] = BD * F + A * E;
+ mat[9] = -B * C;
+ mat[2] = AD * E + B * F;
+ mat[6] = -AD * F + B * E;
+ mat[10] = A * C;
+
+ mat[12] = mat[13] = mat[14] = mat[3] = mat[7] = mat[11] = 0;
+ mat[15] = 1;
+}
+
+static inline float
+clamp (float v, float low, float high)
+{
+ /* This is not very efficient ... */
+ v -= low;
+ while (v > high - low) v -= high - low;
+ while (v < 0) v += high - low;
+ v += low;
+ return v;
+}
+
+/* Convert a rotation matrix to 3 Euler angles. */
+void
+matrix_rotation_to_euler (const float *mat,
+ float *angle_x, float *angle_y, float *angle_z)
+{
+ float C, trx, try;
+
+ *angle_y = -asin( mat[8]); /* Calculate Y-axis angle */
+ C = cos( *angle_y );
+
+ if ( fabs( C ) > 0.005 ) /* Gimball lock? */
+ {
+ trx = mat[10] / C; /* No, so get X-axis angle */
+ try = -mat[9] / C;
+
+ *angle_x = atan2( try, trx );
+
+ trx = mat[0] / C; /* Get Z-axis angle */
+ try = -mat[4] / C;
+
+ *angle_z = atan2( try, trx );
+ }
+ else /* Gimball lock has occurred */
+ {
+ trx = mat[5]; /* And calculate Z-axis angle */
+ try = mat[1];
+
+ *angle_z = atan2( try, trx );
+ }
+
+ /* Clamp all angles to range */
+ *angle_x = clamp (*angle_x, 0, 2 * M_PI);
+ *angle_y = clamp (*angle_y, 0, 2 * M_PI);
+ *angle_z = clamp (*angle_z, 0, 2 * M_PI);
+}
+
+/* This code is taken from Mesa 3.0.
+ */
+void
+matrix_multiply (const float *a, const float *b,
+ float *product)
+{
+ /* This matmul was contributed by Thomas Malik */
+ int i;
+
+#define A(row,col) a[(col<<2)+row]
+#define B(row,col) b[(col<<2)+row]
+#define P(row,col) product[(col<<2)+row]
+
+ /* i-te Zeile */
+ for (i = 0; i < 4; i++) {
+ float ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
+ P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
+ P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
+ P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
+ P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
+ }
+
+#undef A
+#undef B
+#undef P
+}
+
+/* Multiply matrix by vector. */
+void
+matrix_vec_multiply (const float *m, const float *v,
+ float *result)
+{
+ result[0] = m[0]*v[0] + m[1]*v[1] + m[2]*v[2] + m[3]*v[3];
+ result[1] = m[4]*v[0] + m[5]*v[1] + m[6]*v[2] + m[7]*v[3];
+ result[2] = m[8]*v[0] + m[9]*v[1] + m[10]*v[2] + m[11]*v[3];
+ result[3] = m[12]*v[0] + m[13]*v[1] + m[14]*v[2] + m[15]*v[3];
+}
+
+/* Compute the magnitude of a vector. */
+float
+vec_magnitude (const float *v)
+{
+ return sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+}
+
+/* Compute the magnitude of a 2D vector. */
+float
+vec_magnitude2d (const float *v)
+{
+ return sqrt (v[0]*v[0] + v[1]*v[1]);
+}
+
+/* Normalize a vector. */
+void
+vec_normalize (const float *v, float *r)
+{
+ float w = vec_magnitude (v);
+ r[0] = v[0] / w;
+ r[1] = v[1] / w;
+ r[2] = v[2] / w;
+}
+
+/* Normalize a 2D vector. */
+void
+vec_normalize2d (const float *v, float *r)
+{
+ float w = vec_magnitude2d (v);
+ r[0] = v[0] / w;
+ r[1] = v[1] / w;
+}
+
+void
+vec_unit_normal_to_side (float *side, float *normal)
+{
+ float n[3] = { side[0], side[1], side[2] };
+ vec_normalize (n, normal);
+}
+
+/* Compute the dot product of two vectors. */
+float
+vec_dot_product (const float *v1, const float *v2)
+{
+ return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
+}
+
+/* Compute the magnitude of vector v1 in direction vector v2.
+ * If v1 == v2, this returns 1. If v1 = -v2, this returns -1.
+ * If v1 is perpendicular to v2 this returns 0.
+ */
+float
+vec_magnitude_in_direction (const float *v1, const float *v2)
+{
+ static float v1n[3], v2n[3];
+
+ /* Normalize both vectors. */
+ vec_normalize (v1, v1n);
+ vec_normalize (v2, v2n);
+
+ /* Return their dot product. */
+ return vec_dot_product (v1n, v2n);
+}
+
+/* Compute angle between two vectors. */
+float
+vec_angle_between (const float *v1, const float *v2)
+{
+ return acos (vec_magnitude_in_direction (v1, v2));
+}
+
+/* Scale a vector. */
+void
+vec_scale (const float *a, float n, float *r)
+{
+ r[0] = a[0] * n;
+ r[1] = a[1] * n;
+ r[2] = a[2] * n;
+}
+
+/* Add two vectors. */
+void
+vec_add (const float *a, const float *b, float *r)
+{
+ r[0] = a[0] + b[0];
+ r[1] = a[1] + b[1];
+ r[2] = a[2] + b[2];
+}
+
+/* Subtract two vectors. */
+void
+vec_subtract (const float *a, const float *b, float *r)
+{
+ r[0] = a[0] - b[0];
+ r[1] = a[1] - b[1];
+ r[2] = a[2] - b[2];
+}
+
+/* Calculate midpoint. */
+void
+point_midpoint (const float *p1, const float *p2, float *mp)
+{
+ mp[0] = (p1[0] + p2[0]) / 2;
+ mp[1] = (p1[1] + p2[1]) / 2;
+ mp[2] = (p1[2] + p2[2]) / 2;
+}
+
+/* Calculate midpoint (in 2D). */
+void
+point_midpoint2d (const float *p1, const float *p2, float *mp)
+{
+ mp[0] = (p1[0] + p2[0]) / 2;
+ mp[1] = (p1[1] + p2[1]) / 2;
+}
+
+/* Distance between two points. */
+float
+point_distance_to_point (const float *p1, const float *p2)
+{
+ float v[3];
+
+ vec_subtract (p1, p2, v);
+ return vec_magnitude (v);
+}
+
+/* Cross product of vectors v and w.
+ * The cross product is a vector:
+ *
+ * v x w = |v| |w| sin t n^
+ *
+ * where t is the angle between a and
+ * b, and n^ is a normal vector perpendicular
+ * to a and b such that a,b,n^ form a
+ * right-handed set.
+ */
+void
+vec_cross_product (const float *v, const float *w, float *r)
+{
+ r[0] = v[1]*w[2] - v[2]*w[1];
+ r[1] = v[2]*w[0] - v[0]*w[2];
+ r[2] = v[0]*w[1] - v[1]*w[0];
+}
+
+/* Distance between two points. */
+float
+point_distance (const float *p, const float *q)
+{
+ double x = p[0] - q[0];
+ double y = p[1] - q[1];
+ double z = p[2] - q[2];
+ return sqrt (x*x + y*y + z*z);
+}
+
+/* Distance from a point to a plane. */
+float
+point_distance_to_plane (const float *plane, const float *point)
+{
+ float a = plane[0];
+ float b = plane[1];
+ float c = plane[2];
+ float d = plane[3];
+ float x = point[0];
+ float y = point[1];
+ float z = point[2];
+ float t = (a*x + b*y + c*z + d) / - (a*a + b*b + c*c);
+ float t2 = t*t;
+ float dist = sqrt (t2*a*a + t2*b*b + t2*c*c);
+ /* Don't lose the sign of t. */
+ if (t < 0) return dist; else return -dist;
+}
+
+/* Return true if point_distance_to_plane > 0. */
+int
+point_is_inside_plane (const float *plane, const float *point)
+{
+ float a = plane[0];
+ float b = plane[1];
+ float c = plane[2];
+ float d = plane[3];
+ float x = point[0];
+ float y = point[1];
+ float z = point[2];
+ float t = (a*x + b*y + c*z + d) / - (a*a + b*b + c*c);
+
+ return t < 0;
+
+#if 0
+ float t2 = t*t;
+ float dist = sqrt (t2*a*a + t2*b*b + t2*c*c);
+ /* Don't lose the sign of t. */
+ if (t < 0) return dist; else return -dist;
+#endif
+}
+
+/* See: http://www.greuer.de/efaq.html */
+void
+point_footprint_on_line (const float *point,
+ const float *line_point, const float *line_vector,
+ float *footprint)
+{
+ float t;
+ float s[3];
+
+ vec_subtract (point, line_point, s);
+ t = vec_dot_product (s, line_vector) /
+ vec_dot_product (line_vector, line_vector);
+
+ vec_scale (line_vector, t, s);
+ vec_add (line_point, s, footprint);
+}
+
+float
+point_distance_to_line (const float *point,
+ const float *line_point, const float *line_vector)
+{
+#if 0
+ float footprint[3];
+
+ point_footprint_on_line (point, line_point, line_vector, footprint);
+ return point_distance_to_point (point, footprint);
+#else
+ float u[3], p[3], prod[3], dist;
+
+ /* Normalize vector u along the line. */
+ vec_normalize (line_vector, u);
+
+ /* The distance is given by | (p-a) x u | where p is the
+ * point, a is a point on the line and x is the cross product.
+ */
+ vec_subtract (point, line_point, p);
+ vec_cross_product (p, u, prod);
+ dist = vec_magnitude (prod);
+
+ return dist;
+#endif
+}
+
+float
+point_distance_to_line_segment (const float *point,
+ const float *line_point0,
+ const float *line_point1)
+{
+ float t;
+ float s[3], v[3];
+
+ vec_subtract (line_point1, line_point0, v);
+ vec_subtract (point, line_point0, s);
+ t = vec_dot_product (s, v) /
+ vec_dot_product (v, v);
+
+ if (t >= 0 && t <= 1)
+ {
+ float footprint[3];
+
+ vec_scale (v, t, s);
+ vec_add (line_point0, s, footprint);
+ return point_distance_to_point (point, footprint);
+ }
+ else if (t < 0)
+ return point_distance_to_point (point, line_point0);
+ /* else t > 1 */
+ return point_distance_to_point (point, line_point1);
+}
+
+int
+point_lies_in_face (const float *points, int nr_points, const float *point)
+{
+ float sum = point_face_angle_sum (points, nr_points, point);
+ return fabs (sum - 2*M_PI) < 1e-5;
+}
+
+/* See: http://astronomy.swin.edu.au/pbourke/geometry/insidepoly/ */
+float
+point_face_angle_sum (const float *points, int nr_points, const float *point)
+{
+ float sum = 0;
+ int i, next;
+
+ for (i = 0, next = 1; i < nr_points; ++i, ++next)
+ {
+ float p1[3], p2[3], m1, m2, costheta;
+
+ if (next == nr_points) next = 0;
+
+ p1[0] = points[i*3] - point[0];
+ p1[1] = points[i*3+1] - point[1];
+ p1[2] = points[i*3+2] - point[2];
+ p2[0] = points[next*3] - point[0];
+ p2[1] = points[next*3+1] - point[1];
+ p2[2] = points[next*3+2] - point[2];
+
+ m1 = vec_magnitude (p1);
+ m2 = vec_magnitude (p2);
+
+ if (m1 * m2 < 1e-5)
+ return 2 * M_PI;
+ else
+ costheta = (p1[0]*p2[0] + p1[1]*p2[1] + p1[2]*p2[2]) / (m1*m2);
+
+ sum += acos (costheta);
+ }
+
+ return sum;
+}
+
+float
+point_distance_to_face (const float *points, int nr_points,
+ const float *plane, const float *point, int *edge)
+{
+ float my_plane_coeffs[4];
+ float a, b, c, d, tq, q[3], dist;
+ int e, i, next;
+
+ /* Calculate plane coefficients, if necessary. */
+ if (plane == 0)
+ {
+ plane = my_plane_coeffs;
+ plane_coefficients (&points[0], &points[3], &points[6], (float *) plane);
+ }
+
+ a = plane[0];
+ b = plane[1];
+ c = plane[2];
+ d = plane[3];
+
+ /* q is the coordinate of the point of intersection of a
+ * normal line from the point to the plane. It may or may
+ * not be on the bounded face (we'll work that out in the
+ * moment). tq is the parameter of point q.
+ */
+ tq = - (a*point[0] + b*point[1] + c*point[2] + d) / (a*a + b*b + c*c);
+ q[0] = point[0] + tq*a;
+ q[1] = point[1] + tq*b;
+ q[2] = point[2] + tq*c;
+
+ /* Is q on the bounded face? */
+ if (point_lies_in_face (points, nr_points, q))
+ {
+ /* Compute the distance from the point to the plane. */
+ float t2 = tq*tq;
+
+ dist = sqrt (t2*a*a + t2*b*b + t2*c*c);
+
+ if (edge) *edge = -1;
+
+ return tq < 0 ? dist : -dist;
+ }
+
+ /* Find the closest edge. */
+ e = -1;
+ dist = 0;
+
+ for (i = 0, next = 1; i < nr_points; ++i, ++next)
+ {
+ float d;
+
+ if (next == nr_points) next = 0;
+
+ d = point_distance_to_line_segment (point,
+ &points[i*3], &points[next*3]);
+
+ if (e == -1 || d < dist)
+ {
+ dist = d;
+ e = i;
+ }
+ }
+
+ if (edge) *edge = e;
+
+ return tq < 0 ? dist : -dist;
+}
+
+/* Compute the four coefficients of a plane which
+ * uniquely specify that plane, given three points
+ * (not colinear) on the plane. Most of the variables
+ * in this function are redundant (optimized out?),
+ * but they get it into the same form as in
+ * Lansdown, p. 178.
+ */
+void
+plane_coefficients (const float *p, const float *q, const float *r,
+ float *co)
+{
+ float x2 = p[0];
+ float y2 = p[1];
+ float z2 = p[2];
+ float x1 = q[0];
+ float y1 = q[1];
+ float z1 = q[2];
+ float x3 = r[0];
+ float y3 = r[1];
+ float z3 = r[2];
+ float xa = x1 + x2;
+ float xb = x2 + x3;
+ float xc = x3 + x1;
+ float ya = y1 + y2;
+ float yb = y2 + y3;
+ float yc = y3 + y1;
+ float za = z1 + z2;
+ float zb = z2 + z3;
+ float zc = z3 + z1;
+
+ co[0] = (y1-y2) * za + (y2-y3) * zb + (y3-y1) * zc;
+ co[1] = (z1-z2) * xa + (z2-z3) * xb + (z3-z1) * xc;
+ co[2] = (x1-x2) * ya + (x2-x3) * yb + (x3-x1) * yc;
+ co[3] = - (co[0]*x1 + co[1]*y1 + co[2]*z1);
+}
+
+void
+plane_translate_along_normal (const float *plane, float distance,
+ float *new_plane)
+{
+ float w = vec_magnitude (plane);
+
+ new_plane[0] = plane[0];
+ new_plane[1] = plane[1];
+ new_plane[2] = plane[2];
+ new_plane[3] = plane[3] - w * distance;
+}
+
+void
+face_translate_along_normal (const float *points, int nr_points,
+ const float *plane, float distance,
+ float *new_points, float *new_plane)
+{
+ float w = vec_magnitude (plane), nv[3];
+ int i;
+
+ new_plane[0] = plane[0];
+ new_plane[1] = plane[1];
+ new_plane[2] = plane[2];
+ new_plane[3] = plane[3] - w * distance;
+
+ vec_scale (plane, distance / w, nv);
+ for (i = 0; i < nr_points; ++i)
+ {
+ new_points[i*3] = points[i*3] + nv[0];
+ new_points[i*3+1] = points[i*3+1] + nv[1];
+ new_points[i*3+2] = points[i*3+2] + nv[2];
+ }
+}
+
+/* All these quaternion functions are modified from the matrix FAQ again. */
+void
+quaternion_normalize (const float *a, float *r)
+{
+ float w = vec_magnitude (a);
+ r[0] = a[0] / w;
+ r[1] = a[1] / w;
+ r[2] = a[2] / w;
+ r[3] = a[3] / w;
+}
+
+void
+quaternion_conjugate (const float *a, float *r)
+{
+ r[0] = -a[0];
+ r[1] = -a[1];
+ r[2] = -a[2];
+ r[3] = a[3];
+}
+
+float
+quaternion_magnitude (const float *a)
+{
+ return sqrt (a[3]*a[3] + a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
+}
+
+void
+quaternion_multiply (const float *a, const float *b, float *r)
+{
+ float va[3], vb[3], vc[3];
+
+ r[3] = vec_dot_product (a, b);
+
+ vec_cross_product (a, b, va);
+ vec_scale (a, b[3], vb);
+ vec_scale (b, a[3], vc);
+ vec_add (va, vb, va);
+ vec_add (va, vc, r);
+
+ quaternion_normalize (r, r);
+}
+
+void
+quaternion_to_rotation_matrix (const float *q, float *mat)
+{
+ float X = q[0];
+ float Y = q[1];
+ float Z = q[2];
+ float W = q[3];
+
+ float xx = X * X;
+ float xy = X * Y;
+ float xz = X * Z;
+ float xw = X * W;
+
+ float yy = Y * Y;
+ float yz = Y * Z;
+ float yw = Y * W;
+
+ float zz = Z * Z;
+ float zw = Z * W;
+
+ mat[0] = 1 - 2 * ( yy + zz );
+ mat[4] = 2 * ( xy - zw );
+ mat[8] = 2 * ( xz + yw );
+
+ mat[1] = 2 * ( xy + zw );
+ mat[5] = 1 - 2 * ( xx + zz );
+ mat[9] = 2 * ( yz - xw );
+
+ mat[2] = 2 * ( xz - yw );
+ mat[6] = 2 * ( yz + xw );
+ mat[10] = 1 - 2 * ( xx + yy );
+
+ mat[3] = mat[7] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
+ mat[15] = 1;
+}
+
+void
+make_quaternion_from_axis_angle (const float *axis, float angle,
+ float *q)
+{
+ double sin_a = sin (angle / 2);
+ double cos_a = cos (angle / 2);
+
+ q[0] = axis[0] * sin_a;
+ q[1] = axis[1] * sin_a;
+ q[2] = axis[2] * sin_a;
+ q[3] = cos_a;
+
+ quaternion_normalize (q, q);
+}
+
+int
+collision_moving_sphere_and_face (const float *p0, const float *p1,
+ float radius,
+ const float *points, int nr_points,
+ const float *plane,
+ float *collision_point)
+{
+ float my_plane_coeffs[4], raised_plane[4], t, v[3], quot;
+ float raised_points[3 * nr_points];
+
+ /* Get the plane coefficients. */
+ if (plane == 0)
+ {
+ plane = my_plane_coeffs;
+ plane_coefficients (&points[0], &points[3], &points[6], (float *) plane);
+ }
+
+ /* Raise the plane up by the distance of one radius. Then we can
+ * just test for the intersection of the ray and the face.This is
+ * something of an approximation, but hopefully will give us good
+ * results in practice. If not, then we may need to rework this
+ * code. (XXX)
+ */
+ face_translate_along_normal (points, nr_points, plane, radius,
+ raised_points, raised_plane);
+
+ /* Get the intersection point of the ray and the plane, as a
+ * parameter, t.
+ */
+ vec_subtract (p1, p0, v);
+ quot = raised_plane[0]*v[0] + raised_plane[1]*v[1] + raised_plane[2]*v[2];
+ if (fabs (quot)
+#if 0
+ < 1e-5
+#else
+ == 0
+#endif
+ )
+ {
+ /* The path of the sphere is nearly parallel to the plane. Don't
+ * count this as a collision at all.
+ */
+ return 0;
+ }
+
+ t = - (raised_plane[0]*p0[0] + raised_plane[1]*p0[1] + raised_plane[2]*p0[2]
+ + raised_plane[3]) / quot;
+ if (t < 0 || t > 1)
+ {
+ /* There is no collision. */
+ return 0;
+ }
+
+ /* Calculate the actual point of collision. NOTE: This is the centre
+ * of the sphere, NOT the point where the sphere and plane touch.
+ */
+ vec_scale (v, t, v);
+ vec_add (p0, v, collision_point);
+
+ /* Is the collision point actually within the bounded convex polygon
+ * which defines the face? If not, then no collision actually
+ * occurred. Note that we have to translate (ie. raise) the points
+ * list too.
+ */
+ return point_lies_in_face (raised_points, nr_points, collision_point);
+}
--- /dev/null
+/* Matrix and vector arithmetic.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: matvec.h,v 1.3 2001/11/19 17:10:54 rich Exp $
+ */
+
+#ifndef MATVEC_H
+#define MATVEC_H
+
+#include <pool.h>
+#include <math.h>
+
+/* Notes:
+ *
+ * This library only handles 4x4 matrices and 4-vectors, for
+ * basic 3D graphics use. A matrix is just an array float[16]
+ * and a vector is just an array float[4]. You can either allocate
+ * these in a pool using ``new_matrix'' and ``new_vec'', or
+ * else you can allocate them statically.
+ *
+ * All matrices are stored in COLUMN-MAJOR ORDER! This is for
+ * compatibility with OpenGL, but it is the OPPOSITE of the
+ * normal C row-major ordering, so beware. Matrix elements in
+ * column-major order are as follows:
+ *
+ * M = | m0 m4 m8 m12 |
+ * | m1 m5 m9 m13 |
+ * | m2 m6 m10 m14 |
+ * | m3 m7 m11 m15 |
+ *
+ * Some of these functions have been inlined. I only inline
+ * functions based on evidence from profiling the code as a
+ * whole or where the function is so simple that the overhead
+ * of calling it is larger than the inlined code. Excessive
+ * inlining can itself cause performance problems, particularly
+ * on modern processors which are very good at making jumps
+ * and function calls.
+ *
+ */
+
+/* Function: new_matrix - allocate a new matrix or vector
+ * Function: new_vec
+ *
+ * @code{new_matrix} allocates a new 4x4 matrix of floats
+ * in @code{pool}.
+ *
+ * @code{new_vec} allocates a new 4-vector of floats in
+ * @code{pool}.
+ *
+ * You may use these functions to allocate matrices and
+ * vectors dynamically, or you may allocate them statically.
+ * The other matrix and vector functions available do not
+ * distriguish between dynamically and statically allocated
+ * variables.
+ *
+ * Note: All matrices are stored in COLUMN-MAJOR ORDER!
+ * This is for compatibility with OpenGL, but it is the
+ * OPPOSITE of the natural C row-major ordering, so beware.
+ *
+ * See also: @ref{new_identity_matrix(3)}, @ref{new_zero_vec(3)}.
+ */
+#define new_matrix(pool) ((float *) pmalloc ((pool), sizeof (float) * 16))
+#define new_vec(pool) ((float *) pmalloc ((pool), sizeof (float) * 4))
+
+/* Variable: identity_matrix - identity matrix and zero vector
+ * Variable: zero_vec
+ * Function: new_identity_matrix
+ * Function: new_zero_vec
+ * Function: make_identity_matrix
+ * Function: make_zero_vec
+ *
+ * The @code{identity_matrix} variable contains a read-only
+ * copy of the identity matrix. The @code{zero_vec} variable
+ * contains a read-only copy of the zero vector.
+ *
+ * Use @code{new_identity_matrix} to allocate a new
+ * identity matrix variable in @code{pool}. Use @code{new_zero_vec}
+ * to similarly allocate a new zero vector.
+ *
+ * Use @code{make_identity_matrix} to copy the identity
+ * matrix over an existing matrix @code{m}. Use @code{make_zero_vec}
+ * to similarly copy the zero vector over an existing vector @code{v}.
+ *
+ * See also: @ref{new_matrix(3)}, @ref{new_vec(3)}.
+ */
+extern float identity_matrix[16];
+extern float zero_vec[4];
+extern float *new_identity_matrix (pool);
+extern float *new_zero_vec (pool);
+#define make_identity_matrix(m) memcpy (m, identity_matrix, sizeof(float)*16);
+#define make_zero_vec(v) memcpy (v, zero_vec, sizeof (float) * 4);
+
+extern void make_rotation_matrix (float angle,
+ float x, float y, float z,
+ float *m);
+
+extern void make_translation_matrix (float x, float y, float z, float *m);
+
+extern void make_scaling_matrix (float x, float y, float z, float *m);
+
+extern void matrix_euler_to_rotation (float angle_x, float angle_y,
+ float angle_z,
+ float *mat);
+extern void matrix_rotation_to_euler (const float *mat,
+ float *angle_x, float *angle_y,
+ float *angle_z);
+
+extern void matrix_multiply (const float *a, const float *b,
+ float *product);
+
+extern void matrix_vec_multiply (const float *m, const float *v,
+ float *result);
+
+/* Function: vec_magnitude - calculate magnitude (length) of a vector
+ * Function: vec_magnitude2d
+ *
+ * @code{vec_magnitude} calculates the magnitude (length) of a
+ * 3D vector. @code{vec_magnitude2d} calculates the magnitude
+ * of a 2D vector.
+ *
+ * See also: @ref{vec_normalize(3)}, @ref{vec_normalize2d(3)}.
+ */
+extern float vec_magnitude (const float *v);
+extern float vec_magnitude2d (const float *v);
+
+/* Function: vec_normalize - normalize a vector
+ * Function: vec_normalize2d
+ *
+ * These two functions normalize respectively a 3D or 2D
+ * vector @code{v}. The original vector @code{v} is not touched,
+ * and the result is placed in vector @code{r}.
+ *
+ * To normalize a vector in-place (ie. modifying the original
+ * vector), do:
+ *
+ * @code{vec_normalize (v, v);}
+ *
+ * See also: @ref{vec_magnitude(3)}, @ref{vec_magnitude2d(3)}.
+ */
+extern void vec_normalize (const float *v, float *r);
+extern void vec_normalize2d (const float *v, float *r);
+
+extern void vec_unit_normal_to_side (float *side, float *normal);
+
+/* Function: vec_dot_product - calculate the dot product of two vectors
+ *
+ * @code{vec_dot_product} calculates the dot product of two
+ * vectors @code{v1} and @code{v2} and returns it. The dot
+ * product is formally defined as:
+ *
+ * @code{|v1| |v2| cos theta}
+ *
+ * where @code{theta} is the angle between the two vectors.
+ *
+ * One interesting consequence of this is that if both @code{v1}
+ * and @code{v2} are already normalized, then the dot product
+ * is 1 if the vectors are parallel and running in the same
+ * direction, and 0 if the vectors are
+ * perpendicular.
+ *
+ * See also: @ref{vec_magnitude_in_direction(3)}, @ref{vec_angle_between(3)}
+ */
+extern float vec_dot_product (const float *v1, const float *v2);
+
+/* Function: vec_magnitude_in_direction - calculate relative direction of two vectors
+ *
+ * If @code{v1} and @code{v2} are parallel and point in the
+ * same direction, then @code{vec_magnitude_in_direction} returns +1.
+ * If @code{v1} and @code{v2} are perpendicular, this returns
+ * 0. If @code{v1} and @code{v2} are parallel and point in
+ * opposite directions to each other, this returns -1.
+ * For other vectors, this function returns the cosine of
+ * the angle between the vectors.
+ *
+ * See also: @ref{vec_dot_product(3)}, @ref{vec_angle_between(3)}
+ */
+extern float vec_magnitude_in_direction (const float *v1, const float *v2);
+
+/* Function: vec_angle_between - calculate the angle between two vectors
+ *
+ * This function returns the angle between two vectors
+ * @code{v1} and @code{v2}.
+ *
+ * See also: @ref{vec_dot_product(3)}, @ref{vec_magnitude_in_direction(3)}
+ */
+extern float vec_angle_between (const float *v1, const float *v2);
+
+extern void vec_cross_product (const float *v, const float *w, float *r);
+
+extern void vec_scale (const float *a, float n, float *r);
+extern void vec_add (const float *a, const float *b, float *r);
+extern void vec_subtract (const float *a, const float *b, float *r);
+
+float point_distance_to_point (const float *p1, const float *p2);
+
+extern void point_midpoint (const float *p1, const float *p2, float *mp);
+extern void point_midpoint2d (const float *p1, const float *p2, float *mp);
+extern float point_distance (const float *p, const float *q);
+
+/* Function: point_distance_to_plane - distance from point to plane
+ * Function: point_is_inside_plane
+ *
+ * @code{point_distance_to_plane} calculates the (shortest) distance from
+ * the point @code{point} to the plane @code{plane}. This distance is
+ * positive if the point is "inside" the plane -- that is, if the
+ * normal vector drawn from the plane points towards the point. It
+ * is negative if the point is "outside" the plane. It is zero if the
+ * point lies on the plane.
+ *
+ * @code{point_is_inside_plane} returns true if the point is strictly
+ * inside the plane, and false if the point lies on the plane or is
+ * outside. It is much faster to compute this than to use
+ * @code{point_distance_to_plane} and take the sign of the result.
+ *
+ * See also: @ref{plane_coefficients(3)}, @ref{point_distance_to_face(3)}.
+ */
+extern float point_distance_to_plane (const float *plane, const float *point);
+extern int point_is_inside_plane (const float *plane, const float *point);
+
+extern void point_footprint_on_line (const float *point, const float *line_point, const float *line_vector, float *footprint);
+
+/* Function: point_distance_to_line - shortest distance from a point to a line
+ *
+ * Given a @code{point} and a line, expressed as @code{line_point}
+ * and parallel @code{line_vector}, compute the shortest distance
+ * from the point to the line.
+ *
+ * See also: @ref{point_distance_to_plane(3)}, @ref{point_distance_to_face(3)},
+ * @ref{point_distance_to_line_segment(3)}.
+ */
+extern float point_distance_to_line (const float *point, const float *line_point, const float *line_vector);
+
+/* Function: point_distance_to_line_segment - shortest distance from a point to a line segment
+ *
+ * Given a @code{point} and a line segment from @code{line_point0} to
+ * @code{line_point1}, compute the shortest distance from the
+ * point to the line segment.
+ *
+ * See also: @ref{point_distance_to_line(3)}.
+ */
+extern float point_distance_to_line_segment (const float *point, const float *line_point0, const float *line_point1);
+
+/* Function: point_lies_in_face - does a point lie on the interior of a bounded convex polygon
+ * Function: point_face_angle_sum
+ *
+ * Take a bounded convex polygon (a "face") and a point. The function
+ * @code{point_lies_in_face} returns true iff the point is both
+ * (a) coplanar with the face, and
+ * (b) lies inside the edges of the face.
+ *
+ * In order to do this, @code{point_lies_in_face} calls
+ * @code{point_face_angle_sum} which works out the sum of
+ * the interior angles. If conditions (a) and (b) are both
+ * satisfied then the sum of the interior angles will be
+ * very close to 2.PI.
+ *
+ * The face is expressed as a flat list of points (3-vectors).
+ *
+ * See also: @ref{plane_coefficients(3)}, @ref{point_distance_to_face(3)}.
+ */
+extern int point_lies_in_face (const float *points, int nr_points, const float *point);
+extern float point_face_angle_sum (const float *points, int nr_points, const float *point);
+
+/* Function: point_distance_to_face - distance from point to bounded convex polygon (face)
+ *
+ * Given a point and a bounded convex polygon (a "face"), the
+ * function @code{point_distance_to_face} calculates the distance
+ * from the point to the face. There are two importance cases to
+ * consider here:
+ *
+ * (a) The point is directly above or below the face. In other words,
+ * a line dropped from the point perpendicular to the face intersects
+ * the face within the boundary of the polygon. In this case, the
+ * function returns the shortest distance from the point to the
+ * intersection (and is essentially equivalent to
+ * @code{point_distance_to_plane}).
+ *
+ * (b) The point is not directly above or below the face. In this case
+ * the function works out the distance to the nearest edge of the face.
+ *
+ * The face is specified as a list of points and a plane (ie.
+ * plane coefficients). If @code{plane} is @code{NULL}, then the
+ * function calls @ref{plane_coefficients(3)} on your behalf. If
+ * the face is fixed, and you will call this function lots of
+ * times, then it is a good idea to calculate the plane coefficients
+ * once only and cache them.
+ *
+ * Returns: The distance of the point from the face. The distance
+ * will be positive if the point is above the face (ie. inside
+ * the plane: see @ref{point_distance_to_plane(3)}), or negative
+ * otherwise.
+ *
+ * If @code{edge} is not @code{NULL}, then it is set to one of
+ * the following values:
+ *
+ * @code{*edge == -1} if the point is directly above or below
+ * the face, corresponding to case (a) above.
+ *
+ * @code{*edge == 0 .. nr_points-1} if the point is closest to
+ * that particular edge, corresponding to case (b) above.
+ *
+ * See also: @ref{point_distance_to_plane(3)},
+ * @ref{plane_coefficients(3)}, @ref{point_lies_in_face(3)},
+ * @ref{point_distance_to_line(3)}.
+ */
+extern float point_distance_to_face (const float *points, int nr_points, const float *plane, const float *point, int *edge);
+
+/* Function: plane_coefficients - calculate the coefficient form for a plane
+ *
+ * Given three points, not colinear, which naturally form a plane, calculate
+ * the 4-vector form for the plane coefficients. The three points
+ * are passed as @code{p}, @code{q} and @code{r}. The coefficients
+ * are returned in vector @code{co}.
+ *
+ * The four coefficients returned are respectively @code{a}, @code{b},
+ * @code{c} and @code{d} in the standard plane equation:
+ *
+ * @code{a x + b y + c z + d = 0}
+ *
+ * (Note that many texts use @code{- d}, so be warned).
+ *
+ * The normal (perpendicular) vector to the plane may be derived
+ * immediately: it is just @code{(a, b, c)}. Note that the normal
+ * vector is not normalized!
+ *
+ * Planes are unbounded: they stretch off to infinity in all directions.
+ * If what you really want are bounded convex polygons, then you
+ * need to use a c2lib "face".
+ */
+extern void plane_coefficients (const float *p, const float *q, const float *r, float *co);
+
+/* Function: plane_translate_along_normal - translate a plane or face some distance in the direction of the normal
+ * Function: face_translate_along_normal
+ *
+ * Given an existing @code{plane} (expressed as plane coefficients),
+ * produce a new plane @code{new_plane} which has been translated
+ * by @code{distance} units along the direction of the normal. The
+ * new plane is also returned as plane coefficients.
+ *
+ * @code{face_translate_along_normal} is similar, except that it also
+ * translates a list of points by the same distance.
+ *
+ * See also: @ref{plane_coefficients(3)}.
+ */
+extern void plane_translate_along_normal (const float *plane, float distance, float *new_plane);
+extern void face_translate_along_normal (const float *points, int nr_points, const float *plane, float distance, float *new_points, float *new_plane);
+
+extern void quaternion_normalize (const float *a, float *r);
+extern void quaternion_conjugate (const float *a, float *r);
+extern float quaternion_magnitude (const float *a);
+extern void quaternion_multiply (const float *a, const float *b, float *r);
+extern void quaternion_to_rotation_matrix (const float *q, float *mat);
+extern void make_quaternion_from_axis_angle (const float *axis, float angle,
+ float *q);
+
+/* Function: collision_moving_sphere_and_face - detect collision between a moving sphere and a fixed face
+ *
+ * This function detects collisions between a sphere which is moving
+ * at constant speed along a linear path and a fixed bounded
+ * convex polygon ("face").
+ *
+ * The centre of the sphere moves from point @code{p0} to point @code{p1}.
+ * The sphere has radius @code{radius}.
+ *
+ * The face is described by the list of bounding points, and the plane
+ * coefficients of the plane of the face (you may pass @code{plane}
+ * as @code{NULL} in which case the function works out the plane
+ * coefficients for you, although this is generally less efficient).
+ *
+ * Returns: If there was a collision, this function returns true and
+ * sets the collision point in @code{collision_point}. Note that the
+ * collision point is the position of the centre of the sphere at
+ * the point of collision, NOT the place where the sphere touches
+ * the face. If there was no collision, this function returns false.
+ */
+extern int collision_moving_sphere_and_face (const float *p0, const float *p1, float radius, const float *points, int nr_points, const float *plane, float *collision_point);
+
+#endif /* MATVEC_H */
--- /dev/null
+/* An Apache-like pool allocator.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: pool.c,v 1.8 2002/10/13 12:25:42 rich Exp $
+ */
+
+#include "config.h"
+
+#if SIZEOF_VOID_P != SIZEOF_LONG
+#error "This library currently assumes that sizeof (void *) == sizeof (long), which is not the case on your platform. This may cause the library to crash at runtime."
+#endif
+
+/* If set, then calls to pmalloc will initialise the memory to 0xefefef...,
+ * helping to catch uninitialised memory problems. This is very useful for
+ * debugging new code, but should be turned off on production systems.
+ */
+#define DEBUG_UNINITIALISED_MEMORY 1
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <pool.h>
+
+struct _pool_allocs
+{
+ struct _pool_allocs *next;
+
+ /* The flags field contains:
+ * bit 31 == if set, this structure shouldn't be freed
+ * bits 30-16 == number of slots in the structure
+ * bits 15- 0 == number of slots used in the structure.
+ */
+ unsigned flags;
+
+#define _PA_NO_FREE(pa) ((pa)->flags & 0x80000000U)
+#define _PA_SLOTS(pa) (((pa)->flags & 0x7fff0000U) >> 16)
+#define _PA_SLOTS_USED(pa) ((pa)->flags & 0xffffU)
+
+ void *slot[0];
+} __attribute__((packed));
+
+struct _pool_cleanup_slot
+{
+ void (*fn) (void *);
+ void *data;
+};
+
+struct _pool_cleanups
+{
+ struct _pool_cleanups *next;
+
+ /* The flags field contains:
+ * bit 31 == if set, this structure shouldn't be freed
+ * bits 30-16 == number of slots in the structure
+ * bits 15- 0 == number of slots used in the structure.
+ */
+ unsigned flags;
+
+#define _PC_NO_FREE(pc) ((pc)->flags & 0x80000000U)
+#define _PC_SLOTS(pc) (((pc)->flags & 0x7fff0000U) >> 16)
+#define _PC_SLOTS_USED(pc) ((pc)->flags & 0xffffU)
+
+ struct _pool_cleanup_slot slot[0];
+} __attribute__((packed));
+
+#define INITIAL_PA_SLOTS 16U
+#define MAX_PA_SLOTS 16384U /* Must be <= 16384 */
+#define INITIAL_PC_SLOTS 2U
+#define MAX_PC_SLOTS 16384U /* Must be <= 16384 */
+
+struct pool
+{
+ /* If this is a subpool, then this points to the parent. */
+ struct pool *parent_pool;
+
+ /* When subpools are stored on a list, this is used to link the list. */
+ struct pool *next;
+
+ /* Sub-pools. */
+ struct pool *subpool_list;
+
+ /* Pointer to head block of memory allocations. */
+ struct _pool_allocs *allocs;
+
+ /* Pointer to head block of clean-up functions. */
+ struct _pool_cleanups *cleanups;
+};
+
+#ifndef NO_GLOBAL_POOL
+pool global_pool;
+#endif
+
+static int trace_fd = -1;
+static const char *trace_filename = 0;
+
+static void (*bad_malloc_handler) (void) = abort;
+#ifndef NO_GLOBAL_POOL
+static void alloc_global_pool (void) __attribute__((constructor));
+static void free_global_pool (void) __attribute__((destructor));
+#endif
+static void open_trace_file (void) __attribute__((constructor));
+static void trace (const char *fn, void *caller, struct pool *ptr1, void *ptr2, void *ptr3, int i1);
+
+#define TRACE(ptr1, ptr2, ptr3, i1) do { if (trace_filename) trace (__PRETTY_FUNCTION__, __builtin_return_address (0), (ptr1), (ptr2), (ptr3), (i1)); } while (0)
+
+pool
+new_pool ()
+{
+ /* The amount of space required for pool + allocs + cleanups. */
+ const int size
+ = sizeof (struct pool) +
+ sizeof (struct _pool_allocs) +
+ INITIAL_PA_SLOTS * sizeof (void *) +
+ sizeof (struct _pool_cleanups) +
+ INITIAL_PC_SLOTS * sizeof (struct _pool_cleanup_slot);
+
+ pool p = malloc (size);
+ if (p == 0) bad_malloc_handler ();
+
+ memset (p, 0, size);
+
+ p->allocs = (struct _pool_allocs *) ((void *)p + sizeof (struct pool));
+ p->cleanups = (struct _pool_cleanups *)
+ ((void *)p + sizeof (struct pool) + sizeof (struct _pool_allocs)
+ + INITIAL_PA_SLOTS * sizeof (void *));
+
+ p->allocs->flags = 0x80000000U | INITIAL_PA_SLOTS << 16;
+ p->cleanups->flags = 0x80000000U | INITIAL_PC_SLOTS << 16;
+
+ TRACE (p, 0, 0, 0);
+
+ return p;
+}
+
+pool
+new_subpool (pool parent)
+{
+ pool p = new_pool ();
+ p->parent_pool = parent;
+
+ p->next = parent->subpool_list;
+ parent->subpool_list = p;
+
+ TRACE (p, parent, 0, 0);
+
+ return p;
+}
+
+static inline void
+_do_cleanups (pool p)
+{
+ struct _pool_cleanups *pc, *pc_next;
+ int i;
+
+ for (pc = p->cleanups; pc; pc = pc_next)
+ {
+ pc_next = pc->next;
+
+ for (i = 0; i < _PC_SLOTS_USED (pc); ++i)
+ pc->slot[i].fn (pc->slot[i].data);
+ if (!_PC_NO_FREE (pc))
+ free (pc);
+ }
+}
+
+static inline void
+_do_frees (pool p)
+{
+ struct _pool_allocs *pa, *pa_next;
+ int i;
+
+ for (pa = p->allocs; pa; pa = pa_next)
+ {
+ pa_next = pa->next;
+
+ for (i = 0; i < _PA_SLOTS_USED (pa); ++i)
+ free (pa->slot[i]);
+ if (!_PA_NO_FREE (pa))
+ free (pa);
+ }
+}
+
+void
+delete_pool (pool p)
+{
+ _do_cleanups (p);
+
+ /* Clean up any sub-pools. */
+ while (p->subpool_list) delete_pool (p->subpool_list);
+
+ _do_frees (p);
+
+ /* Do I have a parent? If so, remove myself from my parent's subpool
+ * list.
+ */
+ if (p->parent_pool)
+ {
+ pool parent = p->parent_pool, this, last = 0;
+
+ for (this = parent->subpool_list; this; last = this, this = this->next)
+ {
+ if (this == p)
+ {
+ /* Remove this one. */
+ if (last != 0)
+ last->next = this->next;
+ else
+ parent->subpool_list = this->next;
+
+ goto found_me;
+ }
+ }
+
+ abort (); /* Oops - self not found on subpool list. */
+ found_me:;
+ }
+
+ free (p);
+
+ TRACE (p, 0, 0, 0);
+}
+
+void *
+pmalloc (pool p, size_t n)
+{
+ void *ptr;
+
+ ptr = malloc (n);
+ if (ptr == 0) bad_malloc_handler ();
+
+#if DEBUG_UNINITIALISED_MEMORY
+ memset (ptr, 0xef, n);
+#endif
+
+ pool_register_malloc (p, ptr);
+
+ TRACE (p, ptr, 0, n);
+
+ return ptr;
+}
+
+void *
+pcalloc (pool p, size_t nmemb, size_t size)
+{
+ void *ptr = pmalloc (p, nmemb * size);
+ if (ptr) memset (ptr, 0, nmemb * size);
+ return ptr;
+}
+
+void *
+prealloc (pool p, void *ptr, size_t n)
+{
+ struct _pool_allocs *pa;
+ int i;
+ void *new_ptr;
+
+ if (ptr == 0)
+ return pmalloc (p, n);
+
+ new_ptr = realloc (ptr, n);
+ if (new_ptr == 0) bad_malloc_handler ();
+
+ /* XXX This is inefficient. We need to search through the
+ * allocations to find this one and update the pointer.
+ */
+ if (ptr != new_ptr)
+ {
+ for (pa = p->allocs; pa; pa = pa->next)
+ {
+ for (i = 0; i < _PA_SLOTS_USED (pa); ++i)
+ if (pa->slot[i] == ptr)
+ {
+ pa->slot[i] = new_ptr;
+ goto found;
+ }
+ }
+ abort ();
+
+ found:;
+ }
+
+ TRACE (p, ptr, new_ptr, n);
+
+ return new_ptr;
+}
+
+void
+pool_register_cleanup_fn (pool p, void (*fn) (void *), void *data)
+{
+ unsigned nr_slots;
+ struct _pool_cleanups *pc;
+
+ if (_PC_SLOTS_USED (p->cleanups) < _PC_SLOTS (p->cleanups))
+ {
+ again:
+ p->cleanups->slot[_PC_SLOTS_USED(p->cleanups)].fn = fn;
+ p->cleanups->slot[_PC_SLOTS_USED(p->cleanups)].data = data;
+ p->cleanups->flags++;
+ return;
+ }
+
+ /* Allocate a new block of cleanup slots. */
+ nr_slots = _PC_SLOTS (p->cleanups);
+ if (nr_slots < MAX_PC_SLOTS)
+ nr_slots *= 2;
+
+ pc = malloc (sizeof (struct _pool_cleanups) +
+ nr_slots * sizeof (struct _pool_cleanup_slot));
+ if (pc == 0) bad_malloc_handler ();
+ pc->next = p->cleanups;
+ pc->flags = nr_slots << 16;
+ p->cleanups = pc;
+
+ goto again;
+}
+
+void
+pool_register_malloc (pool p, void *ptr)
+{
+ unsigned nr_slots;
+ struct _pool_allocs *pa;
+
+ if (_PA_SLOTS_USED (p->allocs) < _PA_SLOTS (p->allocs))
+ {
+ again:
+ p->allocs->slot[_PA_SLOTS_USED(p->allocs)] = ptr;
+ p->allocs->flags++;
+ return;
+ }
+
+ /* Allocate a new block of slots. */
+ nr_slots = _PA_SLOTS (p->allocs);
+ if (nr_slots < MAX_PA_SLOTS)
+ nr_slots *= 2;
+
+ pa = malloc (sizeof (struct _pool_allocs) + nr_slots * sizeof (void *));
+ if (pa == 0) bad_malloc_handler ();
+ pa->next = p->allocs;
+ pa->flags = nr_slots << 16;
+ p->allocs = pa;
+
+ goto again;
+}
+
+static void
+_pool_close (void *fdv)
+{
+ long fd = (long) fdv;
+ close (fd);
+}
+
+void
+pool_register_fd (pool p, int fd)
+{
+ pool_register_cleanup_fn (p, _pool_close, (void *) (long) fd);
+}
+
+#ifndef NO_GLOBAL_POOL
+static void
+alloc_global_pool ()
+{
+ global_pool = new_pool ();
+}
+
+static void
+free_global_pool ()
+{
+ delete_pool (global_pool);
+}
+#endif /* !NO_GLOBAL_POOL */
+
+void (*
+pool_set_bad_malloc_handler (void (*fn) (void))) (void)
+{
+ void (*old_fn) (void) = bad_malloc_handler;
+ bad_malloc_handler = fn;
+ return old_fn;
+}
+
+static int
+_get_struct_size (const pool p)
+{
+ pool subpool;
+ struct _pool_allocs *pa;
+ struct _pool_cleanups *pc;
+ int size;
+
+ size = sizeof (*p);
+
+ for (pa = p->allocs; pa; pa = pa->next)
+ size += sizeof (struct _pool_allocs)
+ + _PA_SLOTS (pa) * sizeof (void *);
+
+ for (pc = p->cleanups; pc; pc = pc->next)
+ size += sizeof (struct _pool_cleanups)
+ + _PC_SLOTS (pc) * sizeof (struct _pool_cleanup_slot);
+
+ for (subpool = p->subpool_list; subpool; subpool = subpool->next)
+ size += _get_struct_size (subpool);
+
+ return size;
+}
+
+static int
+_get_nr_subpools (const pool p)
+{
+ pool subpool;
+ int count = 1;
+
+ for (subpool = p->subpool_list; subpool; subpool = subpool->next)
+ count += _get_nr_subpools (subpool);
+
+ return count;
+}
+
+void
+pool_get_stats (const pool p, struct pool_stats *stats, size_t n)
+{
+ struct pool_stats s;
+
+ s.nr_subpools = _get_nr_subpools (p);
+ s.struct_size = _get_struct_size (p);
+
+ memcpy (stats, &s, n);
+}
+
+static void
+open_trace_file ()
+{
+ char msg1[] =
+ "\n"
+ "Pool allocator running in trace mode.\n"
+ "Trace is being saved to file ";
+ char msg2[] = "\n\n";
+
+ trace_filename = getenv ("POOL_TRACE");
+
+ if (trace_filename)
+ {
+ trace_fd = open (trace_filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (trace_fd == -1)
+ {
+ perror (trace_filename);
+ exit (1);
+ }
+
+ write (2, msg1, sizeof msg1);
+ write (2, trace_filename, strlen (trace_filename));
+ write (2, msg2, sizeof msg2);
+ }
+}
+
+static void
+trace (const char *fn, void *caller, struct pool *ptr1, void *ptr2, void *ptr3, int i1)
+{
+ char buffer[128];
+
+ sprintf (buffer,
+ "%s caller: %p ptr1: %p ptr2: %p ptr3: %p i1: %d\n",
+ fn, caller, ptr1, ptr2, ptr3, i1);
+ write (trace_fd, buffer, strlen (buffer));
+}
--- /dev/null
+/* An Apache-like pool allocator.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: pool.h,v 1.7 2002/06/08 11:50:44 rich Exp $
+ */
+
+#ifndef POOL_H
+#define POOL_H
+
+#include <stdlib.h>
+
+struct pool;
+typedef struct pool *pool;
+
+/* Function: new_pool - allocate a new pool
+ *
+ * Allocate a new pool. Pools must eventually be deleted explicitly
+ * by calling @ref{delete_pool(3)}.
+ *
+ * Note that @code{new_pool} is now deprecated. It is almost always
+ * better to create a subpool of the global pool, ie:
+ *
+ * @code{pool = new_subpool (global_pool);}
+ *
+ * This has the distinct advantage that your new pool will be cleaned
+ * up properly if the process calls @code{exit}.
+ *
+ * See also: @ref{new_subpool(3)}, @ref{global_pool(3)},
+ * @ref{delete_pool(3)}.
+ */
+extern pool new_pool (void);
+
+/* Function: new_subpool - allocate a subpool of an existing pool
+ *
+ * Allocate a new subpool. The pool may either be deleted explicitly, or
+ * else is deleted implicitly when the parent pool is deleted.
+ */
+extern pool new_subpool (pool);
+
+/* Function: delete_pool - delete a pool
+ *
+ * Delete a pool or subpool. This also deletes any subpools that the
+ * pool may own (and recursively subpools of those subpools, etc.)
+ */
+extern void delete_pool (pool);
+
+/* Function: pmalloc - allocate memory in a pool
+ * Function: pcalloc
+ * Function: prealloc
+ *
+ * Allocate memory in a pool or, if pool is null, on the main heap
+ * (equivalent to plain @code{malloc}). If memory is allocated in a real
+ * pool, then it is automatically freed when the pool is deleted.
+ *
+ * Memory returned is word-aligned.
+ *
+ * If a memory allocation fails, the @code{bad_malloc_handler} function is
+ * called (which defaults to just calling @ref{abort(3)}).
+ *
+ * @code{pcalloc} is identical to @code{pmalloc} but also sets the memory
+ * to zero before returning it.
+ *
+ * @code{prealloc} increases the size of an existing memory allocation.
+ * @code{prealloc} might move the memory in the process of reallocating it.
+ *
+ * Bugs: @code{prealloc} cannot reduce the size of an existing memory
+ * allocation.
+ */
+extern void *pmalloc (pool, size_t n);
+extern void *pcalloc (pool, size_t nmemb, size_t size);
+extern void *prealloc (pool, void *ptr, size_t n);
+
+/* Function: pool_register_malloc - allow pool to own malloc'd memory
+ *
+ * Register an anonymous area of malloc-allocated memory which
+ * will be freed (with @ref{free(3)}) when the pool is deleted.
+ */
+extern void pool_register_malloc (pool, void *ptr);
+
+/* Function: pool_register_fd - allow pool to own file descriptor
+ *
+ * Register a file descriptor to be closed when the pool is deleted.
+ * There is no way to unregister a file descriptor. If you wish to
+ * do that, then you probably want to register the fd in a subpool.
+ */
+extern void pool_register_fd (pool, int fd);
+
+/* Function: pool_register_cleanup_fn - call function when pool is deleted
+ *
+ * Register a function to be called when the pool is deleted. There
+ * is no way to unregister this function. If you wish to do that, then
+ * you probably want to register it in a subpool.
+ */
+extern void pool_register_cleanup_fn (pool, void (*fn) (void *), void *data);
+
+/* Function: pool_set_bad_malloc_handler - set handler for when malloc fails
+ *
+ * Set the function which is called when an underlying malloc or realloc
+ * operation fails. The default is that @ref{abort(3)} is called.
+ *
+ * This function returns the previous handler.
+ */
+extern void (*pool_set_bad_malloc_handler (void (*fn) (void))) (void);
+
+struct pool_stats
+{
+ int nr_subpools;
+ int struct_size;
+};
+
+/* Function: pool_get_stats - get statistics from the pool
+ *
+ * Return various statistics collected for the pool. This function
+ * fills in the @code{stats} argument which should point to a
+ * structure of type @code{struct pool_stats}. @code{n} should be
+ * set to the size of this structure.
+ *
+ * @code{struct pool_stats} currently contains the following fields:
+ *
+ * @code{nr_subpools}: The number of subpools (including the current pool).
+ *
+ * @code{struct_size}: The memory overhead used by the pool allocator
+ * itself to store structures. This includes subpools.
+ */
+extern void pool_get_stats (const pool, struct pool_stats *stats, size_t n);
+
+/* Obsolete calls for backwards compatibility. These will be removed soon. */
+#define pool_get_size(p) (-1)
+#define pool_get_areas(p) (-1)
+#define pool_get_allocations(p) (-1)
+#define pool_nr_subpools(p) (-1)
+
+#ifndef NO_GLOBAL_POOL
+/* Variable: global_pool - the global pool for global allocations
+ *
+ * This is the global pool which is allocated before @code{main()} is called
+ * and deleted automatically upon program exit. Items allocated on this
+ * pool cannot be deleted until the program ends, and so it is a good
+ * idea not to allocate short-lived items here.
+ */
+extern pool global_pool;
+#endif /* !NO_GLOBAL_POOL */
+
+#endif /* POOL_H */
--- /dev/null
+/* String functions which allocate strings on the pool.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: pre.c,v 1.3 2003/01/22 14:29:37 rich Exp $
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <pcre.h>
+
+#include <pool.h>
+#include <vector.h>
+#include <pstring.h>
+#include <pre.h>
+
+/* These private functions are used to capture memory allocations made
+ * by the PCRE library.
+ */
+static void *malloc_in_pool (size_t);
+static void do_nothing (void *);
+static pool malloc_pool = 0;
+
+pcre *
+precomp (pool pool, const char *pattern, int options)
+{
+ const char *errptr;
+ int erroffset;
+ pcre *result;
+ void *(*old_malloc)(size_t);
+ void (*old_free) (void *);
+
+ /* Allocations to the pool. */
+ old_malloc = pcre_malloc;
+ old_free = pcre_free;
+ pcre_malloc = malloc_in_pool;
+ malloc_pool = pool;
+ pcre_free = do_nothing;
+
+ /* Compile the pattern. */
+ result = pcre_compile (pattern, options, &errptr, &erroffset, 0);
+ if (result == 0)
+ {
+ fprintf (stderr,
+ "pcre: internal error compiling regular expression:\n"
+ "pcre: %s\n"
+ "pcre: %s\n"
+ "pcre: %s^\n",
+ errptr,
+ pattern,
+ pchrs (pool, ' ', erroffset-1));
+ exit (1);
+ }
+
+ /* Restore memory allocation. */
+ pcre_malloc = old_malloc;
+ pcre_free = old_free;
+
+ return result;
+}
+
+vector
+prematch (pool pool, const char *str, const pcre *pattern, int options)
+{
+ int err, n, i, ovecsize;
+ int *ovector;
+ vector result;
+ void *(*old_malloc)(size_t);
+ void (*old_free) (void *);
+
+ /* Allocations to the pool. */
+ old_malloc = pcre_malloc;
+ old_free = pcre_free;
+ pcre_malloc = malloc_in_pool;
+ malloc_pool = pool;
+ pcre_free = do_nothing;
+
+ /* Get the number of capturing substrings in the pattern (n). */
+ if ((err = pcre_fullinfo (pattern, 0, PCRE_INFO_CAPTURECOUNT, &n)) != 0)
+ abort ();
+
+ /* Allocate a vector large enough to contain the resulting substrings. */
+ ovecsize = (n+1) * 3;
+ ovector = alloca (ovecsize * sizeof (int));
+
+ /* Do the match. n is the number of strings found. */
+ n = pcre_exec (pattern, 0, str, strlen (str), 0, options, ovector, ovecsize);
+
+ /* Restore memory allocation. */
+ pcre_malloc = old_malloc;
+ pcre_free = old_free;
+
+ if (n == PCRE_ERROR_NOMATCH) /* No match, return NULL. */
+ return 0;
+ else if (n <= 0) /* Some other error. */
+ abort ();
+
+ /* Some matches. Construct the vector. */
+ result = new_vector (pool, char *);
+ for (i = 0; i < n; ++i)
+ {
+ char *s = 0;
+ int start = ovector[i*2];
+ int end = ovector[i*2+1];
+
+ if (start >= 0)
+ s = pstrndup (pool, str + start, end - start);
+ vector_push_back (result, s);
+ }
+
+ return result;
+}
+
+static int do_match_and_sub (pool pool, const char *str, char **newstrp,
+ const pcre *pattern, const char *sub,
+ int startoffset, int options, int cc,
+ int *ovector, int ovecsize, int placeholders);
+
+const char *
+presubst (pool pool, const char *str,
+ const pcre *pattern, const char *sub,
+ int options)
+{
+ char *newstr = pstrdup (pool, "");
+ int cc, err, n, ovecsize;
+ int *ovector;
+ void *(*old_malloc)(size_t);
+ void (*old_free) (void *);
+ int placeholders = (options & PRESUBST_NO_PLACEHOLDERS) ? 0 : 1;
+ int global = (options & PRESUBST_GLOBAL) ? 1 : 0;
+
+ options &= ~(PRESUBST_NO_PLACEHOLDERS | PRESUBST_GLOBAL);
+
+ /* Allocations to the pool. */
+ old_malloc = pcre_malloc;
+ old_free = pcre_free;
+ pcre_malloc = malloc_in_pool;
+ malloc_pool = pool;
+ pcre_free = do_nothing;
+
+ /* Get the number of capturing substrings in the pattern. */
+ if ((err = pcre_fullinfo (pattern, 0, PCRE_INFO_CAPTURECOUNT, &cc)) != 0)
+ abort ();
+
+ /* Allocate a vector large enough to contain the resulting substrings. */
+ ovecsize = (cc+1) * 3;
+ ovector = alloca (ovecsize * sizeof (int));
+
+ /* Find a match and substitute. */
+ n = do_match_and_sub (pool, str, &newstr, pattern, sub, 0, options, cc,
+ ovector, ovecsize, placeholders);
+
+ if (global)
+ {
+ /* Do the remaining matches. */
+ while (n > 0)
+ {
+ n = do_match_and_sub (pool, str, &newstr, pattern, sub, n,
+ options, cc,
+ ovector, ovecsize, placeholders);
+ }
+ }
+ else if (n > 0)
+ {
+ /* Concatenate the remainder of the string. */
+ newstr = pstrcat (pool, newstr, str + n);
+ }
+
+ /* Restore memory allocation. */
+ pcre_malloc = old_malloc;
+ pcre_free = old_free;
+
+ return newstr;
+}
+
+static int
+do_match_and_sub (pool pool, const char *str, char **newstrp,
+ const pcre *pattern, const char *sub,
+ int startoffset, int options, int cc,
+ int *ovector, int ovecsize, int placeholders)
+{
+ int so, eo, err;
+ char *newstr = *newstrp;
+
+ /* Find the next match. */
+ err = pcre_exec (pattern, 0, str, strlen (str), startoffset,
+ options, ovector, ovecsize);
+ if (err == PCRE_ERROR_NOMATCH) /* No match. */
+ {
+ if (startoffset == 0)
+ /* Special case: we can just return the original string. */
+ *newstrp = (char *) str;
+ else
+ {
+ /* Concatenate the end of the string. */
+ newstr = pstrcat (pool, newstr, str + startoffset);
+ *newstrp = newstr;
+ }
+ return -1;
+ }
+ else if (err != cc+1) /* Some other error. */
+ abort ();
+
+ /* Get position of the match. */
+ so = ovector[0];
+ eo = ovector[1];
+
+ /* Substitute for the match. */
+ newstr = pstrncat (pool, newstr, str + startoffset, so - startoffset);
+ if (placeholders)
+ {
+ int i;
+
+ /* Substitute $1, $2, ... placeholders with captured substrings. */
+ for (i = 0; i < strlen (sub); ++i)
+ {
+ if (sub[i] == '$' && (sub[i+1] >= '0' && sub[i+1] <= '9'))
+ {
+ int n = sub[i+1] - '0';
+
+ if (n > cc)
+ newstr = pstrncat (pool, newstr, &sub[i], 2);
+ else
+ {
+ int nso = ovector[n*2];
+ int neo = ovector[n*2+1];
+
+ newstr = pstrncat (pool, newstr, str+nso, neo-nso);
+ }
+
+ i++;
+ }
+ else
+ newstr = pstrncat (pool, newstr, &sub[i], 1);
+ }
+ }
+ else
+ newstr = pstrcat (pool, newstr, sub);
+
+ *newstrp = newstr;
+ return eo;
+}
+
+static void *
+malloc_in_pool (size_t n)
+{
+ return pmalloc (malloc_pool, n);
+}
+
+static void
+do_nothing (void *p)
+{
+ /* Yes, really, do nothing. */
+}
--- /dev/null
+/* Regular expression functions which allocate in the pool.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: pre.h,v 1.1 2002/10/05 16:42:04 rich Exp $
+ */
+
+#ifndef PRE_H
+#define PRE_H
+
+#include <pcre.h>
+
+#include <pool.h>
+#include <vector.h>
+
+/* Function: precomp - Compile, match, substitute regular expressions.
+ * Function: prematch
+ * Function: presubst
+ *
+ * These functions are wrappers around the Perl Compatible
+ * Regular Expressions (PCRE) library (see
+ * @code{http://www.pcre.org/}).
+ *
+ * @code{precomp} compiles the regular expression @code{pattern}
+ * returning a pointer to the opaque @code{pcre} structure. The
+ * structure is allocated in @code{pool}. The @code{options} argument
+ * is a list of PCRE options, passed directly to the
+ * @code{pcre_compile} function (see @ref{pcre(3)}). You
+ * should normally set @code{options} to 0.
+ *
+ * @code{prematch} matches the string @code{str} with the
+ * compiled regular expression @code{pattern}.
+ *
+ * If there is no match, this returns @code{NULL}. If the string
+ * matches, then this function returns a @code{vector} of @code{char *},
+ * allocated in @code{pool}. The first element of this vector is
+ * the portion of the original string which matched the whole
+ * pattern. The second and subsequent elements of this vector are
+ * captured substrings. It is possible in rare circumstances for some
+ * of these captured substrings to be @code{NULL} (see the
+ * @ref{pcre(3)} manual page for an example).
+ *
+ * The @code{options} argument is passed directly to
+ * @code{pcre_exec}. You should normally set @code{options} to 0.
+ *
+ * @code{presubst} substitutes @code{sub} for @code{pattern}
+ * wherever @code{pattern} occurs in @code{str}. It is equivalent
+ * to the @code{str =~ s/pat/sub/} function in Perl.
+ *
+ * Placeholders @code{$1}, @code{$2}, etc. in @code{sub} are
+ * substituted for the matching substrings of @code{pattern}.
+ * Placeholder substitution can be disabled completely by
+ * including the @code{PRESUBST_NO_PLACEHOLDERS} flag in @code{options}.
+ *
+ * If the @code{PRESUBST_GLOBAL} flag is given, then all
+ * matches are substituted. Otherwise only the first match
+ * is substituted.
+ *
+ * The @code{options} argument is passed to @code{pcre_exec}
+ * (after removing the @code{PRESUBST_*} flags).
+ *
+ * The return value from @code{presubst} is the string with
+ * replacements.
+ *
+ * See also: @ref{pcre(3)}.
+ */
+pcre *precomp (pool pool, const char *pattern, int options);
+vector prematch (pool pool, const char *str, const pcre *pattern, int options);
+const char *presubst (pool pool, const char *str, const pcre *pattern, const char *sub, int options);
+
+#define PRESUBST_NO_PLACEHOLDERS 0x10000000
+#define PRESUBST_GLOBAL 0x20000000
+
+#endif /* PRE_H */
--- /dev/null
+/* String functions which allocate strings on the pool.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: pstring.c,v 1.24 2003/01/22 14:29:37 rich Exp $
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <vector.h>
+#include <hash.h>
+#include <pstring.h>
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+/* Duplicate a string. */
+char *
+pstrdup (pool pool, const char *str)
+{
+ int len = strlen (str);
+ char *ptr = pmalloc (pool, (len+1) * sizeof (char));
+ return memcpy (ptr, str, len+1);
+}
+
+/* Duplicate up to the first N characters of a string. */
+char *
+pstrndup (pool pool, const char *str, int n)
+{
+ int len = MIN (strlen (str), n);
+ char *ptr = pmalloc (pool, (len+1) * sizeof (char));
+ memcpy (ptr, str, len);
+ ptr[len] = '\0';
+ return ptr;
+}
+
+/* Duplicate a fixed-size area of memory. */
+void *
+pmemdup (pool pool, const void *data, size_t size)
+{
+ void *ptr = pmalloc (pool, size);
+ return memcpy (ptr, data, size);
+}
+
+static vector generic_split (pool pool, const char *str, const void *sep, const char *(*find) (const char *str, const void *sep, const char **end_match), int keep);
+
+static const char *
+find_strstr (const char *str, const void *sep, const char **end_match)
+{
+ const char *csep = (const char *) sep;
+ const char *t = strstr (str, csep);
+ if (t) *end_match = t + strlen (csep);
+ return t;
+}
+
+vector
+pstrsplit (pool pool, const char *str, const char *sep)
+{
+ return generic_split (pool, str, sep, find_strstr, 0);
+}
+
+static const char *
+find_strchr (const char *str, const void *sep, const char **end_match)
+{
+ char c = * (const char *) sep;
+ const char *t = strchr (str, c);
+ if (t) *end_match = t+1;
+ return t;
+}
+
+vector
+pstrcsplit (pool pool, const char *str, char c)
+{
+ return generic_split (pool, str, &c, find_strchr, 0);
+}
+
+static const char *
+find_re (const char *str, const void *sep, const char **end_match)
+{
+ const pcre *re = (const pcre *) sep;
+#define ovecsize 3
+ int ovector[ovecsize];
+ int r = pcre_exec (re, 0, str, strlen (str), 0, 0, ovector, ovecsize);
+
+ if (r >= 0) /* Successful match. */
+ {
+ int so = ovector[0];
+ int eo = ovector[1];
+
+ if (so == -1) abort (); /* Bad pattern. */
+ *end_match = str + eo;
+ return str + so;
+ }
+ else if (r == PCRE_ERROR_NOMATCH)
+ return 0;
+ else
+ abort (); /* Some other error reported by PCRE. */
+#undef ovecsize
+}
+
+vector
+pstrresplit (pool pool, const char *str, const pcre *re)
+{
+ return generic_split (pool, str, re, find_re, 0);
+}
+
+vector
+pstrsplit2 (pool pool, const char *str, const char *sep)
+{
+ return generic_split (pool, str, sep, find_strstr, 1);
+}
+
+vector
+pstrcsplit2 (pool pool, const char *str, char c)
+{
+ return generic_split (pool, str, &c, find_strchr, 1);
+}
+
+vector
+pstrresplit2 (pool pool, const char *str, const pcre *re)
+{
+ return generic_split (pool, str, re, find_re, 1);
+}
+
+/* Generic split function. */
+static vector
+generic_split (pool pool, const char *str, const void *sep,
+ const char *(*find) (const char *str, const void *sep,
+ const char **end_match),
+ int keep)
+{
+ const char *start_match, *end_match;
+ char *s;
+ vector v;
+
+ /* If the string is zero length, always return a zero length vector. */
+ if (strcmp (str, "") == 0) return new_vector (pool, char *);
+
+ /* Find the splitting point. */
+ start_match = find (str, sep, &end_match);
+
+ if (start_match != 0) /* Successful match. */
+ {
+ s = start_match > str ? pstrndup (pool, str, start_match - str) : 0;
+ v = generic_split (pool, end_match, sep, find, keep);
+ if (keep) /* Keep the matching text. */
+ {
+ const char *match;
+
+ match = pstrndup (pool, start_match, end_match - start_match);
+ vector_push_front (v, match);
+ }
+ if (s) vector_push_front (v, s);
+ }
+ else /* Not successful match. */
+ {
+ s = pstrdup (pool, str);
+ v = new_vector (pool, char *);
+ vector_push_back (v, s);
+ }
+
+ return v;
+}
+
+/* Concatenate a vector of strings to form a string. */
+char *
+pconcat (pool pool, vector v)
+{
+ int i;
+ char *s = pstrdup (pool, "");
+
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ char *t;
+
+ vector_get (v, i, t);
+ s = pstrcat (pool, s, t);
+ }
+
+ return s;
+}
+
+/* Join a vector of strings, separating each string by the given string. */
+char *
+pjoin (pool pool, vector v, const char *sep)
+{
+ int i;
+ char *s = pstrdup (pool, "");
+
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ char *t;
+
+ vector_get (v, i, t);
+ s = pstrcat (pool, s, t);
+ if (i < vector_size (v) - 1) s = pstrcat (pool, s, sep);
+ }
+
+ return s;
+}
+
+char *
+pchrs (pool pool, char c, int n)
+{
+ char *s = pmalloc (pool, sizeof (char) * (n + 1));
+ int i;
+
+ for (i = 0; i < n; ++i)
+ s[i] = c;
+ s[n] = '\0';
+
+ return s;
+}
+
+char *
+pstrs (pool pool, const char *str, int n)
+{
+ int len = strlen (str);
+ char *s = pmalloc (pool, sizeof (char) * (len * n + 1));
+ int i, j;
+
+ for (i = j = 0; i < n; ++i, j += len)
+ memcpy (&s[j], str, len);
+
+ s[len * n] = '\0';
+
+ return s;
+}
+
+vector
+pvector (pool pool, ...)
+{
+ va_list args;
+ const char *s;
+ vector v = new_vector (pool, const char *);
+
+ va_start (args, pool);
+ while ((s = va_arg (args, const char *)) != 0)
+ vector_push_back (v, s);
+ va_end (args);
+
+ return v;
+}
+
+vector
+pvectora (pool pool, const char *array[], int n)
+{
+ int i;
+ vector v = new_vector (pool, const char *);
+
+ for (i = 0; i < n; ++i)
+ vector_push_back (v, array[i]);
+
+ return v;
+}
+
+/* Sort a vector of strings. */
+void
+psort (vector v, int (*compare_fn) (const char **, const char **))
+{
+ vector_sort (v, (int (*) (const void *, const void *)) compare_fn);
+}
+
+/* Remove line endings (either CR, CRLF or LF) from the string. */
+char *
+pchomp (char *line)
+{
+ int len = strlen (line);
+
+ while (line[len-1] == '\n' || line[len-1] == '\r')
+ line[--len] = '\0';
+
+ return line;
+}
+
+char *
+ptrimfront (char *str)
+{
+ char *p;
+ int len;
+
+ for (p = str; *p && isspace ((int) *p); ++p)
+ ;
+
+ len = strlen (p);
+ memmove (str, p, len + 1);
+
+ return str;
+}
+
+char *
+ptrimback (char *str)
+{
+ int len;
+ char *p;
+
+ len = strlen (str);
+ for (p = str + len - 1; p >= str && isspace ((int) *p); --p)
+ ;
+
+ p[1] = '\0';
+
+ return str;
+}
+
+char *
+ptrim (char *str)
+{
+ ptrimback (str);
+ ptrimfront (str);
+ return str;
+}
+
+/* This is equivalent to sprintf but it allocates the result string in POOL.*/
+char *
+psprintf (pool pool, const char *format, ...)
+{
+ va_list args;
+ char *s;
+
+ va_start (args, format);
+ s = pvsprintf (pool, format, args);
+ va_end (args);
+
+ return s;
+}
+
+/* Similar to vsprintf. */
+char *
+pvsprintf (pool pool, const char *format, va_list args)
+{
+#ifdef HAVE_VASPRINTF
+
+ char *s;
+
+ vasprintf (&s, format, args);
+ if (s == 0) abort (); /* XXX Should call bad_malloc_handler. */
+
+ /* The pool will clean up the malloc when it goes. */
+ pool_register_malloc (pool, s);
+
+ return s;
+
+#else /* !HAVE_VASPRINTF */
+
+ int r, n = 256;
+ char *s = alloca (n), *t;
+
+ /* Note: according to the manual page, a return value of -1 indicates
+ * that the string was truncated. We have found that this is not
+ * actually true however. In fact, the library seems to return the
+ * number of characters which would have been written into the string
+ * excluding the '\0' (ie. r > n).
+ */
+ r = vsnprintf (s, n, format, args);
+
+ if (r < n)
+ {
+ /* Copy the string into a pool-allocated area of the correct size
+ * and return it.
+ */
+ n = r + 1;
+ t = pmalloc (pool, n);
+ memcpy (t, s, n);
+
+ return t;
+ }
+ else
+ {
+ /* String was truncated. Allocate enough space for the string
+ * in the pool and repeat the vsnprintf into this buffer.
+ */
+ n = r + 1;
+ t = pmalloc (pool, n);
+
+ vsnprintf (t, n, format, args);
+
+ return t;
+ }
+
+#endif /* !HAVE_VASPRINTF */
+}
+
+/* Convert various number types to strings. */
+char *
+pitoa (pool pool, int n)
+{
+ char *s = pmalloc (pool, 16);
+ snprintf (s, 16, "%d", n);
+ return s;
+}
+
+char *
+pdtoa (pool pool, double n)
+{
+ char *s = pmalloc (pool, 16);
+ snprintf (s, 16, "%f", n);
+ return s;
+}
+
+char *
+pxtoa (pool pool, unsigned n)
+{
+ char *s = pmalloc (pool, 16);
+ snprintf (s, 16, "%x", n);
+ return s;
+}
+
+/* Promote vector of numbers to vector of strings. */
+vector
+pvitostr (pool pool, vector v)
+{
+ vector nv = new_vector (pool, char *);
+ int i;
+
+ vector_reallocate (nv, vector_size (v));
+
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ char *s;
+ int j;
+
+ vector_get (v, i, j);
+ s = pitoa (pool, j);
+ vector_push_back (nv, s);
+ }
+
+ return nv;
+}
+
+vector
+pvdtostr (pool pool, vector v)
+{
+ vector nv = new_vector (pool, char *);
+ int i;
+
+ vector_reallocate (nv, vector_size (v));
+
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ char *s;
+ double j;
+
+ vector_get (v, i, j);
+ s = pdtoa (pool, j);
+ vector_push_back (nv, s);
+ }
+
+ return nv;
+}
+
+vector
+pvxtostr (pool pool, vector v)
+{
+ vector nv = new_vector (pool, char *);
+ int i;
+
+ vector_reallocate (nv, vector_size (v));
+
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ char *s;
+ unsigned j;
+
+ vector_get (v, i, j);
+ s = pxtoa (pool, j);
+ vector_push_back (nv, s);
+ }
+
+ return nv;
+}
+
+/* STR is a string allocated in POOL. Append ENDING to STR, reallocating
+ * STR if necessary.
+ */
+char *
+pstrcat (pool pool, char *str, const char *ending)
+{
+ /* There are probably more efficient ways to implement this ... */
+ int slen = strlen (str);
+ int elen = strlen (ending);
+
+ str = prealloc (pool, str, slen + elen + 1);
+ strcat (str, ending);
+ return str;
+}
+
+char *
+pstrncat (pool pool, char *str, const char *ending, size_t n)
+{
+ int slen = strlen (str);
+ int elen = strlen (ending);
+
+ elen = elen > n ? n : elen;
+
+ str = prealloc (pool, str, slen + elen + 1);
+ strncat (str, ending, n);
+ return str;
+}
+
+/* Return the substring starting at OFFSET and of length LEN of STR, allocated
+ * as a new string. If LEN is negative, everything up to the end of STR
+ * is returned.
+ */
+char *
+psubstr (pool pool, const char *str, int offset, int len)
+{
+ char *new_str;
+
+ if (len >= 0)
+ {
+ new_str = pmalloc (pool, len + 1);
+ memcpy (new_str, str + offset, len);
+ new_str[len] = '\0';
+ return new_str;
+ }
+ else
+ {
+ len = strlen (str + offset);
+ new_str = pmalloc (pool, len + 1);
+ memcpy (new_str, str + offset, len);
+ new_str[len] = '\0';
+ return new_str;
+ }
+}
+
+char *
+pstrupr (char *str)
+{
+ char *s = str;
+ while (*s) { *s = toupper (*s); s++; }
+ return str;
+}
+
+char *
+pstrlwr (char *str)
+{
+ char *s = str;
+ while (*s) { *s = tolower (*s); s++; }
+ return str;
+}
+
+/* NB. The following figures were derived by examining a large number
+ * of configuration files in /etc/ on a Red Hat Linux box.
+ */
+#define _PGETL_INITIAL_BUFFER 96
+#define _PGETL_INCR_BUFFER 32
+
+char *
+pgetline (pool pool, FILE *fp, char *line)
+{
+ int allocated = _PGETL_INITIAL_BUFFER;
+ int len = 0;
+ int c;
+
+ /* Reallocate the buffer. */
+ line = prealloc (pool, line, _PGETL_INITIAL_BUFFER);
+
+ /* Read in the line until we reach EOF or a '\n' character. */
+ while ((c = getc (fp)) != EOF && c != '\n')
+ {
+ if (len == allocated)
+ line = prealloc (pool, line, allocated += _PGETL_INCR_BUFFER);
+ line[len++] = c;
+ }
+
+ /* EOF and no content? */
+ if (c == EOF && len == 0)
+ return 0;
+
+ /* Last character is '\r'? Remove it. */
+ if (line[len-1] == '\r')
+ len--;
+
+ /* Append a '\0' character to the buffer. */
+ if (len == allocated)
+ line = prealloc (pool, line, ++allocated);
+ line[len] = '\0';
+
+ return line;
+}
+
+char *
+pgetlinex (pool pool, FILE *fp, char *line, const char *comment_set,
+ int flags)
+{
+ int i, len;
+
+ again:
+ /* Read a single line. */
+ line = pgetline (pool, fp, line);
+ if (line == 0) return 0;
+
+ len = strlen (line);
+
+ /* Concatenate? */
+ if (!(flags & PGETL_NO_CONCAT))
+ {
+ another_concat:
+ if (line[len-1] == '\\')
+ {
+ char *next;
+
+ line[--len] = '\0'; /* Remove backslash char from first line. */
+
+ next = pgetline (pool, fp, 0);
+ if (next)
+ {
+ line = pstrcat (pool, line, next);
+ len = strlen (line);
+ goto another_concat;
+ }
+ }
+ }
+
+ /* Remove comments? */
+ if (!(flags & PGETL_INLINE_COMMENTS))
+ {
+ /* No inline comments. We're searching for whitespace followed
+ * by a comment character. If we find it, remove the line following
+ * the comment character.
+ */
+ for (i = 0; i < len; ++i)
+ if (!isspace ((int) line[i]))
+ {
+ if (strchr (comment_set, line[i]) != 0)
+ {
+ line[i] = '\0';
+ len = i;
+ }
+ break;
+ }
+ }
+ else
+ {
+ /* Inline comments. Search for the first occurance of any
+ * comment character and just remove the rest of the line
+ * from that point.
+ */
+ for (i = 0; i < len; ++i)
+ if (strchr (comment_set, line[i]) != 0)
+ {
+ line[i] = '\0';
+ len = i;
+ break;
+ }
+ }
+
+ /* Trim the line. */
+ ptrim (line);
+
+ /* Ignore blank lines. */
+ if (line[0] == '\0')
+ goto again;
+
+ return line;
+}
+
+vector
+pmap (pool p, const vector v, char *(*map_fn) (pool, const char *))
+{
+ int i;
+ vector nv = new_vector (p, char *);
+
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ const char *s;
+ char *r;
+
+ vector_get (v, i, s);
+ r = map_fn (p, s);
+ vector_push_back (nv, r);
+ }
+
+ return nv;
+}
+
+vector
+pgrep (pool p, const vector v, int (*grep_fn) (pool, const char *))
+{
+ int i;
+ vector nv = new_vector (p, char *);
+
+ for (i = 0; i < vector_size (v); ++i)
+ {
+ const char *s;
+
+ vector_get (v, i, s);
+ if (grep_fn (p, s))
+ vector_push_back (nv, s);
+ }
+
+ return nv;
+}
--- /dev/null
+/* String functions which allocate strings on the pool.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: pstring.h,v 1.16 2002/12/04 21:03:25 rich Exp $
+ */
+
+#ifndef PSTRING_H
+#define PSTRING_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <pcre.h>
+
+#include <pool.h>
+#include <vector.h>
+
+/* Function: pstrdup - duplicate a string or area of memory
+ * Function: pstrndup
+ * Function: pmemdup
+ *
+ * @code{pstrdup} duplicates string @code{s}, allocating new memory for the
+ * string in pool @code{pool}.
+ *
+ * @code{pstrndup} duplicates just the first @code{n} characters of the
+ * string.
+ *
+ * @code{pmemdup} duplicates an arbitrary area of memory of size
+ * @code{size} bytes starting at address @code{data}.
+ */
+extern char *pstrdup (pool, const char *s);
+extern char *pstrndup (pool, const char *s, int n);
+extern void *pmemdup (pool, const void *data, size_t size);
+
+/* Function: pstrsplit - split a string on a character, string or regexp.
+ * Function: pstrcsplit
+ * Function: pstrresplit
+ * Function: pstrsplit2
+ * Function: pstrcsplit2
+ * Function: pstrresplit2
+ *
+ * These functions split string @code{str} on either a string
+ * @code{sep}, a character @code{c} or a regular expression @code{re}.
+ *
+ * The result is a vector of newly created substrings.
+ *
+ * The @code{*2} variants split the string in the same way
+ * on the regular expression, but keeps the matching splitting text as
+ * separate elements in the vector. To illustrate this, imagine that
+ * @code{pstrresplit} and @code{pstrresplit2} are called on the string
+ * "This text is <b>bold</b>" with the regular expression @code{[<>]}.
+ *
+ * @code{pstrresplit} will return a vector containing:
+ *
+ * @code{ ( "This text is ", "b", "bold", "/b" ) }
+ *
+ * whereas @code{pstrcsplit2} will return:
+ *
+ * @code{ ( "This text is ", "<", "b", ">", "bold", "<", "/b", ">" ) }
+ *
+ * Note that the first element of the vector might be splitting
+ * text, or might be ordinary text as in the example above. Also
+ * the elements may not be interleaved like this (think about
+ * what would happen if the original string contained @code{"<b></b>"}).
+ * The only way to decide would be to call @code{prematch} on each element.
+ *
+ * This turns out to be very useful for certain sorts of simple
+ * parsing, or if you need to reconstruct the original string (just
+ * concatenate all of the elements together using @code{pconcat}).
+ *
+ * In common with Perl's @code{split} function, all of these functions
+ * return a zero length vector if @code{str} is the empty string.
+ *
+ * See also: @ref{prematch(3)}, @ref{pconcat(3)}.
+ */
+extern vector pstrsplit (pool, const char *str, const char *sep);
+extern vector pstrcsplit (pool, const char *str, char c);
+extern vector pstrresplit (pool, const char *str, const pcre *re);
+extern vector pstrsplit2 (pool, const char *str, const char *sep);
+extern vector pstrcsplit2 (pool, const char *str, char c);
+extern vector pstrresplit2 (pool, const char *str, const pcre *re);
+
+/* Function: pconcat - concatenate a vector of strings
+ * Function: pjoin
+ *
+ * @code{pconcat} concatenates a vector of strings to form a string.
+ *
+ * @code{pjoin} is similar except that @code{sep} is inserted between
+ * each concatenated string in the output.
+ *
+ * @code{pjoin} is kind of the opposite of @ref{pstrsplit(3)}.
+ */
+extern char *pconcat (pool, vector);
+extern char *pjoin (pool, vector, const char *sep);
+
+/* Function: pchrs - generate a string of n repeated characters or strings
+ * Function: pstrs
+ *
+ * @code{pchrs (pool, 'c', n)} is similar to the Perl expression
+ * @code{'c' x n}. It generates a pool-allocated string of @code{n} copies
+ * of character @code{'c'}.
+ *
+ * @code{pstrs (pool, str, n)} is similar to the Perl expression
+ * @code{str x n}. It generates a pool-allocated string of @code{n} copies
+ * of the string @code{str}.
+ */
+extern char *pchrs (pool, char c, int n);
+extern char *pstrs (pool, const char *str, int n);
+
+/* Function: pvector - generate a vector from a list or array of strings
+ * Function: pvectora
+ *
+ * @code{pvector} takes a NULL-terminated list of strings as arguments
+ * and returns a vector of strings. @code{pvectora} takes a pointer to
+ * an array of strings and the number of strings and returns a vector
+ * of strings.
+ *
+ * A typical use of this is to quickly concatenate strings:
+ *
+ * @code{s = pconcat (pool, pvector (pool, s1, s2, s3, NULL));}
+ *
+ * which is roughly equivalent to:
+ *
+ * @code{s = psprintf (pool, "%s%s%s", s1, s2, s3);}
+ *
+ * See also: @ref{pconcat(3)}, @ref{psprintf(3)}.
+ */
+extern vector pvector (pool, ...);
+extern vector pvectora (pool, const char *array[], int n);
+
+/* Function: psort - sort a vector of strings
+ *
+ * Sort a vector of strings, using @code{compare_fn} to compare
+ * strings. The vector is sorted in-place.
+ *
+ * It is a common mistake to try to use @code{strcmp} directly
+ * as your comparison function. This will not work. See the
+ * C FAQ, section 12, question 12.2
+ * (@code{http://www.lysator.liu.se/c/c-faq/c-12.html}).
+ */
+extern void psort (vector, int (*compare_fn) (const char **, const char **));
+
+/* Function: pchomp - remove line endings from a string
+ *
+ * Remove line endings (either CR, CRLF or LF) from the string argument.
+ * The string is modified in-place and a pointer to the string
+ * is also returned.
+ */
+extern char *pchomp (char *line);
+
+/* Function: ptrim - remove whitespace from the ends of a string
+ * Function: ptrimfront
+ * Function: ptrimback
+ *
+ * @code{ptrim} modifies a string of text in place, removing any
+ * whitespace characters from the beginning and end of the line.
+ *
+ * @code{ptrimfront} is the same as @code{ptrim} but only removes
+ * whitespace from the beginning of a string.
+ *
+ * @code{ptrimback} is the same as @code{ptrim} but only removes
+ * whitespace from the end of a string.
+ */
+extern char *ptrim (char *str);
+extern char *ptrimfront (char *str);
+extern char *ptrimback (char *str);
+
+/* Function: psprintf - sprintf which allocates the result in a pool
+ * Function: pvsprintf
+ *
+ * The @code{psprintf} function is equivalent to @code{sprintf}
+ * but it allocates the result string in @code{pool}.
+ *
+ * @code{pvsprintf} works similarly to @code{vsprintf}.
+ */
+extern char *psprintf (pool, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+extern char *pvsprintf (pool, const char *format, va_list ap);
+
+/* Function: pitoa - convert number types to strings
+ * Function: pdtoa
+ * Function: pxtoa
+ *
+ * These functions convert a decimal @code{int}, @code{double} or
+ * hexadecimal @code{unsigned} into a string, which is allocated
+ * in @code{pool}.
+ *
+ * @code{pitoa} is equivalent to @code{psprintf (pool, "%d", i)},
+ * and the other functions have similar equivalents.
+ */
+extern char *pitoa (pool, int);
+extern char *pdtoa (pool, double);
+extern char *pxtoa (pool, unsigned);
+
+/* Function: pvitostr - convert vectors of numbers to vectors of strings
+ * Function: pvdtostr
+ * Function: pvxtostr
+ *
+ * Promote vector of numbers to vector of strings.
+ *
+ * @code{pvitostr} expects a vector of @code{int}.
+ *
+ * @code{pvdtostr} expects a vector of @code{double}.
+ *
+ * @code{pvxtostr} expects a vector of hexadecimal @code{unsigned}.
+ *
+ * All functions return a vector of @code{char *}.
+ */
+extern vector pvitostr (pool, vector);
+extern vector pvdtostr (pool, vector);
+extern vector pvxtostr (pool, vector);
+
+/* Function: pstrcat - extend a string
+ * Function: pstrncat
+ *
+ * @code{str} is a string allocated in @code{pool}.
+ * Append @code{ending} to @code{str}, reallocating
+ * @code{str} if necessary.
+ *
+ * Because @code{str} may be reallocated (ie. moved) you
+ * must invoke this function as follows:
+ *
+ * @code{str = pstrcat (pool, str, ending);}
+ *
+ * @code{pstrncat} is similar to @code{pstrcat} except that
+ * only the first @code{n} characters of @code{ending}
+ * are appended to @code{str}.
+ */
+extern char *pstrcat (pool, char *str, const char *ending);
+extern char *pstrncat (pool, char *str, const char *ending, size_t n);
+
+/* Function: psubstr - return a substring of a string
+ *
+ * Return the substring starting at @code{offset} and of length
+ * @code{len} of @code{str}, allocated
+ * as a new string. If @code{len} is negative,
+ * everything up to the end of @code{str}
+ * is returned.
+ */
+extern char *psubstr (pool, const char *str, int offset, int len);
+
+/* Function: pstrupr - convert a string to upper- or lowercase
+ * Function: pstrlwr
+ *
+ * Convert a string, in-place, to upper or lowercase by applying
+ * @code{toupper} or @code{tolower} to each character in turn.
+ */
+extern char *pstrupr (char *str);
+extern char *pstrlwr (char *str);
+
+/* Function: pgetline - read a line from a file, optionally removing comments
+ * Function: pgetlinex
+ * Function: pgetlinec
+ *
+ * @code{pgetline} reads a single line from a file and returns it. It
+ * allocates enough space to read lines of arbitrary length. Line ending
+ * characters ('\r' and '\n') are automatically removed from the end
+ * of the line.
+ *
+ * The @code{pool} argument is a pool for allocating the line. The
+ * @code{fp} argument is the C @code{FILE} pointer. The @code{line}
+ * argument is a pointer to a string allocated in pool which will
+ * be reallocated and filled with the contents of the line. You may
+ * pass @code{line} as @code{NULL} to get a newly allocated buffer.
+ *
+ * Use @code{pgetline} in one of the following two ways:
+ *
+ * @code{line = pgetline (pool, fp, line);}
+ *
+ * or
+ *
+ * @code{line = pgetline (pool, fp, NULL);}
+ *
+ * @code{pgetlinex} is a more advanced function which reads a line
+ * from a file, optionally removing comments, concatenating together
+ * lines which have been split with a backslash, and ignoring blank
+ * lines. @code{pgetlinex} (and the related macro @code{pgetlinec}) are
+ * very useful for reading lines of input from a configuration file.
+ *
+ * The @code{pool} argument is a pool for allocating the line. The
+ * @code{fp} argument is the C @code{FILE} pointer. The @code{line}
+ * argument is a buffer allocated in pool which will be reallocated
+ * and filled with the result. @code{comment_set} is the set of
+ * possible comment characters -- eg. @code{"#!"} to allow either
+ * @code{#} or @code{!} to be used to introduce comments.
+ * @code{flags} is zero or more of the following flags OR-ed
+ * together:
+ *
+ * @code{PGETL_NO_CONCAT}: Don't concatenate lines which have been
+ * split with trailing backslash characters.
+ *
+ * @code{PGETL_INLINE_COMMENTS}: Treat everything following a comment
+ * character as a comment. The default is to only allow comments which
+ * appear on a line on their own.
+ *
+ * @code{pgetlinec} is a helper macro which calls @code{pgetlinex}
+ * with @code{comment_set == "#"} and @code{flags == 0}.
+ */
+extern char *pgetline (pool, FILE *fp, char *line);
+extern char *pgetlinex (pool, FILE *fp, char *line, const char *comment_set, int flags);
+#define pgetlinec(p,fp,line) pgetlinex ((p), (fp), (line), "#", 0)
+
+#define PGETL_NO_CONCAT 1
+#define PGETL_INLINE_COMMENTS 2
+
+/* Function: pmap - map, search vectors of strings
+ * Function: pgrep
+ *
+ * @code{pmap} takes a @code{vector} of strings (@code{char *}) and
+ * transforms it into another @code{vector} of strings by applying
+ * the function @code{char *map_fn (pool, const char *)} to each
+ * string.
+ *
+ * @code{pgrep} applies the function @code{int grep_fn (pool, const char *)}
+ * to each element in a @code{vector} of strings, and returns a
+ * new vector of strings containing only those strings where
+ * @code{grep_fn} returns true.
+ *
+ * See also: @ref{vector_map_pool(3)}, @ref{vector_grep_pool(3)}.
+ */
+vector pmap (pool, const vector v, char *(*map_fn) (pool, const char *));
+vector pgrep (pool, const vector v, int (*grep_fn) (pool, const char *));
+
+#endif /* PSTRING_H */
--- /dev/null
+/* Test the hash class.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_hash.c,v 1.1 2001/02/08 12:51:31 rich Exp $
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <pool.h>
+#include <vector.h>
+#include <pstring.h>
+#include <hash.h>
+
+/* You can't take the address of non-lvalues in C (ie. you can't
+ * evaluate expressions like "&2"). Hence the following constant
+ * definitions are necessary.
+ */
+const int one = 1;
+const int two = 2;
+const int three = 3;
+const int four = 4;
+const int five = 5;
+const int six = 6;
+const int nine = 9;
+const int sixteen = 16;
+const int twentyfour = 24;
+const int twentyfive = 25;
+const int thirtyfive = 35;
+const int thirtysix = 36;
+
+int
+main ()
+{
+ hash h;
+ pool pool = new_pool ();
+ int v;
+ vector keys, values;
+
+ /* Create a int -> int hash. */
+ h = new_hash (pool, int, int);
+
+ /* Insert some new values. */
+ if (hash_insert (h, one, one) != 0) abort ();
+ if (hash_insert (h, two, four) != 0) abort ();
+ if (hash_insert (h, three, nine) != 0) abort ();
+ if (hash_insert (h, four, sixteen) != 0) abort ();
+ if (hash_insert (h, five, twentyfour) != 0) abort (); /* sic */
+ if (hash_insert (h, six, thirtyfive) != 0) abort (); /* sic */
+
+ /* This should replace existing values. */
+ if (hash_insert (h, five, twentyfive) == 0) abort ();
+ if (hash_insert (h, six, thirtysix) == 0) abort ();
+
+ /* Retrieve some values. */
+ if (hash_get (h, one, v) == 0 || v != 1) abort ();
+ if (hash_get (h, six, v) == 0 || v != 36) abort ();
+ if (hash_get (h, two, v) == 0 || v != 4) abort ();
+ if (hash_get (h, five, v) == 0 || v != 25) abort ();
+
+ /* Copy the hash. */
+ h = copy_hash (pool, h);
+
+ /* Erase a key and check that it no longer exists. */
+ if (hash_erase (h, one) == 0) abort ();
+ if (hash_get (h, one, v) != 0) abort ();
+
+ /* Get list of keys and values. */
+ keys = hash_keys (h);
+ values = hash_values (h);
+
+ printf ("keys = [ %s ]\n",
+ pjoin (pool, pvitostr (pool, keys), ", "));
+ printf ("values = [ %s ]\n",
+ pjoin (pool, pvitostr (pool, values), ", "));
+
+ delete_pool (pool);
+ exit (0);
+}
--- /dev/null
+/* Test matrix, vector arithmetic.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_matvec.c,v 1.2 2001/11/19 17:10:55 rich Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <math.h>
+
+#include "pool.h"
+#include "matvec.h"
+
+static inline int
+is_equal (float a, float b)
+{
+ return fabs (a - b) < 1e-6;
+}
+
+static void
+test_identity_zero ()
+{
+ pool p = new_subpool (global_pool);
+ float *m = new_identity_matrix (p);
+ float *v = new_zero_vec (p);
+
+ assert (m[0] == 1 && m[1] == 0 && m[2] == 0 && m[3] == 0 &&
+ m[4] == 0 && m[5] == 1 && m[6] == 0 && m[7] == 0 &&
+ m[8] == 0 && m[9] == 0 && m[10] == 1 && m[11] == 0 &&
+ m[12] == 0 && m[13] == 0 && m[14] == 0 && m[15] == 1);
+ assert (v[0] == 0 && v[1] == 0 && v[2] == 0 && v[3] == 1);
+
+ delete_pool (p);
+}
+
+static void
+test_mag_norm ()
+{
+ float v[3] = {2, 0, 0}, r[3];
+
+ assert (vec_magnitude (v) == 2);
+ assert (vec_magnitude2d (v) == 2);
+
+ vec_normalize (v, r);
+ assert (r[0] == 1 && r[1] == 0 && r[2] == 0);
+
+ vec_normalize2d (v, r);
+ assert (r[0] == 1 && r[1] == 0);
+}
+
+static void
+test_dot_product ()
+{
+ float v1[3] = { 1, 0, 0 }, v2[3] = { 0, 1, 0 }, v3[3] = { 1, 1, 0 };
+
+ /* Dot product of perpendicular vectors is 0. */
+ assert (vec_dot_product (v1, v2) == 0);
+
+ /* Dot product of identical normal vectors is 1. */
+ assert (vec_dot_product (v1, v1) == 1);
+
+ /* Angle between vectors. */
+ assert (vec_angle_between (v1, v1) == 0);
+ assert (is_equal (vec_angle_between (v1, v2), M_PI/2));
+ assert (is_equal (vec_angle_between (v1, v3), M_PI/4));
+}
+
+static void
+test_point_line ()
+{
+ float p[3], v[3], q[3], d;
+
+ /* Line running along the x axis. */
+ p[0] = 0; p[1] = 0; p[2] = 0; v[0] = 1; v[1] = 0; v[2] = 0;
+
+ q[0] = 0; q[1] = 0; q[2] = 0;
+ assert (point_distance_to_line (q, p, v) == 0);
+
+ q[0] = 1; q[1] = 0; q[2] = 0;
+ assert (point_distance_to_line (q, p, v) == 0);
+
+ q[0] = 0; q[1] = 1; q[2] = 0;
+ assert (point_distance_to_line (q, p, v) == 1);
+
+ q[0] = 0; q[1] = 0; q[2] = 1;
+ assert (point_distance_to_line (q, p, v) == 1);
+
+ q[0] = 2; q[1] = 1; q[2] = 0;
+ assert (point_distance_to_line (q, p, v) == 1);
+
+ /* Line running diagonally x-y. */
+ p[0] = 2; p[1] = 2; p[2] = 0; v[0] = 1; v[1] = 1; v[2] = 0;
+
+ q[0] = 0; q[1] = 0; q[2] = 0;
+ assert (point_distance_to_line (q, p, v) == 0);
+
+ q[0] = 1; q[1] = 0; q[2] = 0;
+ d = point_distance_to_line (q, p, v);
+ assert (is_equal (d * d, 0.5));
+}
+
+static void
+test_point_plane ()
+{
+ float p[3], q[3], r[3], pl[4];
+
+ p[0] = 0; p[1] = 0; p[2] = 0;
+ q[0] = 2; q[1] = 0; q[2] = 0;
+ r[0] = 2; r[1] = 2; r[2] = 0;
+ plane_coefficients (p, q, r, pl);
+
+ assert (pl[3] == 0);
+ vec_normalize (pl, pl);
+ assert (pl[0] == 0 && pl[1] == 0 && pl[2] == -1);
+
+ assert (point_distance_to_plane (pl, p) == 0);
+ assert (point_distance_to_plane (pl, q) == 0);
+ assert (point_distance_to_plane (pl, r) == 0);
+
+ p[0] = 5; p[1] = 5; p[2] = -3;
+ assert (point_distance_to_plane (pl, p) == 3);
+ assert (point_is_inside_plane (pl, p));
+
+ p[0] = 5; p[1] = 5; p[2] = 3;
+ assert (point_distance_to_plane (pl, p) == -3);
+ assert (!point_is_inside_plane (pl, p));
+}
+
+static void
+test_point_in_face ()
+{
+ float points[4][3] = {
+ { 0, 0, 0 },
+ { 1, 1, 0 },
+ { 1, 1, 1 },
+ { 0, 0, 1 }
+ };
+ float p[3];
+
+ p[0] = 0.5; p[1] = 0.5; p[2] = 0.5;
+ assert (point_lies_in_face ((float *) points, 4, p));
+
+ p[0] = 0.01; p[1] = 0.01; p[2] = 0.9;
+ assert (point_lies_in_face ((float *) points, 4, p));
+
+ p[0] = 0; p[1] = 0; p[2] = 0;
+ assert (point_lies_in_face ((float *) points, 4, p));
+
+ p[0] = 1; p[1] = 1; p[2] = 1;
+ assert (point_lies_in_face ((float *) points, 4, p));
+
+ p[0] = 1; p[1] = 0; p[2] = 0;
+ assert (!point_lies_in_face ((float *) points, 4, p));
+
+ p[0] = 1; p[1] = 1; p[2] = -1;
+ assert (!point_lies_in_face ((float *) points, 4, p));
+
+ p[0] = 0.5; p[1] = 0.5; p[2] = 2;
+ assert (!point_lies_in_face ((float *) points, 4, p));
+}
+
+static void
+test_point_to_face ()
+{
+ float points[4][3] = {
+ { 0, 0, 0 },
+ { 1, 0, 0 },
+ { 1, 1, 0 },
+ { 0, 1, 0 }
+ };
+ float p[3];
+ int edge;
+
+ p[0] = 0.5; p[1] = 0.5; p[2] = 0;
+ assert (point_distance_to_face ((float *) points, 4, 0, p, &edge) == 0
+ && edge == -1);
+
+ p[0] = 0.5; p[1] = 0.5; p[2] = 1;
+ assert (point_distance_to_face ((float *) points, 4, 0, p, &edge) == -1
+ && edge == -1);
+
+ p[0] = 0.5; p[1] = 0.5; p[2] = -1;
+ assert (point_distance_to_face ((float *) points, 4, 0, p, &edge) == 1
+ && edge == -1);
+
+ p[0] = -1; p[1] = 0.5; p[2] = 0;
+ assert (point_distance_to_face ((float *) points, 4, 0, p, &edge) == -1
+ && edge == 3);
+}
+
+int
+main ()
+{
+ test_identity_zero ();
+ test_mag_norm ();
+ test_dot_product ();
+ test_point_line ();
+ test_point_plane ();
+ test_point_in_face ();
+ test_point_to_face ();
+
+ exit (0);
+}
--- /dev/null
+/* Test pools, subpools, memory allocation and so on.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_pool.c,v 1.5 2002/12/07 15:18:26 rich Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* Implement a simple malloc debugger -- which counts allocations and
+ * frees and ensures that all memory allocated by the pool code is
+ * evenually freed.
+ */
+
+static void trace_init (void);
+static void trace_finish (void);
+static void *trace_malloc (size_t n, const char *filename, int line);
+static void *trace_realloc (void *p, size_t n, const char *filename, int line);
+static void trace_free (void *p);
+
+#define malloc(n) trace_malloc ((n), __FILE__, __LINE__);
+#define realloc(p,n) trace_realloc ((p), (n), __FILE__, __LINE__);
+#define free(p) trace_free ((p));
+
+#define NO_GLOBAL_POOL 1
+
+#include "pool.h"
+#include "pool.c"
+
+static void test (void);
+
+int
+main ()
+{
+ trace_init ();
+ test ();
+ trace_finish ();
+ exit (0);
+}
+
+/* Perform the tests. */
+static void
+simple_alloc_test ()
+{
+ pool p;
+ int i;
+
+ p = new_pool ();
+
+ for (i = 0; i < 1000; ++i)
+ {
+ pmalloc (p, 1);
+ pmalloc (p, 1);
+ prealloc (p, pmalloc (p, 200), 300);
+ pmalloc (p, 1000);
+ prealloc (p, pmalloc (p, 1000), 1001);
+ prealloc (p, pmalloc (p, 900), 901);
+ pmalloc (p, 1);
+ pmalloc (p, 4);
+ pmalloc (p, 8);
+ pmalloc (p, 1);
+ pmalloc (p, 400);
+ }
+
+ delete_pool (p);
+}
+
+static void
+simple_subpool_test (pool parent, int level)
+{
+ pool p;
+ int i;
+
+ if (level >= 8) return;
+
+ if (parent)
+ {
+ /* The following two statements must remain together. */
+ p = new_subpool (parent);
+ prealloc (p, prealloc (p, pmalloc (p, 16), 100),
+ 200);
+ /* End of realloc test. */
+
+ pcalloc (p, 4, 4);
+ prealloc (p, 0, 8);
+ prealloc (p, pmalloc (p, 4), 8);
+ pmalloc (parent, 1);
+ prealloc (parent, pmalloc (parent, 8), 8);
+ prealloc (parent, pmalloc (parent, 8), 16);
+ }
+ else
+ {
+ p = new_pool ();
+ prealloc (p, pmalloc (p, 4), 8);
+ pmalloc (p, 8);
+ pmalloc (p, 1);
+ }
+
+ for (i = 0; i < 3; ++i)
+ {
+ simple_subpool_test (p, level+1);
+ pmalloc (p, 1);
+ if (parent) pmalloc (parent, 1);
+ }
+
+ if (parent == 0 || level == 4)
+ delete_pool (p);
+}
+
+/* This is a regression test: we had reason to believe this didn't work
+ * at one point.
+ */
+static void
+create_delete_test ()
+{
+ pool p;
+
+ p = new_pool ();
+ delete_pool (p);
+}
+
+static int cleanup_called = 0;
+
+static void
+cleanup_fn (void *v)
+{
+ cleanup_called ++;
+}
+
+static void
+cleanup_fn_test ()
+{
+ pool p, sp1, sp2;
+
+ p = new_pool ();
+ pool_register_cleanup_fn (p, cleanup_fn, 0);
+ delete_pool (p);
+ assert (cleanup_called == 1);
+
+ p = new_pool ();
+ sp1 = new_subpool (p);
+ sp2 = new_subpool (p);
+ pool_register_cleanup_fn (p, cleanup_fn, 0);
+ pool_register_cleanup_fn (sp1, cleanup_fn, 0);
+ pool_register_cleanup_fn (sp2, cleanup_fn, 0);
+ delete_pool (sp1);
+ assert (cleanup_called == 2);
+ delete_pool (p);
+ assert (cleanup_called == 4);
+}
+
+static void
+cleanup_fd_test ()
+{
+ int fd;
+ pool p;
+
+ p = new_pool ();
+ fd = open ("/dev/null", O_RDONLY);
+ pool_register_fd (p, fd);
+ delete_pool (p);
+
+ assert (close (fd) == -1 && errno == EBADF);
+}
+
+static void
+cleanup_malloc_test ()
+{
+ void *m;
+ pool p;
+
+ p = new_pool ();
+ m = malloc (10);
+ pool_register_malloc (p, m);
+ delete_pool (p);
+}
+
+static void
+lots_of_pmalloc_test ()
+{
+ pool p;
+ pool *subpools;
+ int i, j, np = 0;
+
+ /* This test kind of simulates what the chat server does, in an
+ * attempt to find the putative memory leak.
+ */
+ p = new_pool ();
+ subpools = pcalloc (p, sizeof (struct pool), 100);
+
+ for (i = 0; i < 10000; ++i)
+ {
+ if (subpools[np] != 0)
+ delete_pool (subpools[np]);
+ subpools[np] = new_subpool (p);
+
+ for (j = 0; j < 100; ++j)
+ {
+ void *ptr = pmalloc (subpools[np], 100);
+ prealloc (subpools[np], ptr, 200);
+ }
+
+ np++;
+ if (np == 100) np = 0;
+ }
+
+ delete_pool (p);
+}
+
+static void
+test ()
+{
+ simple_alloc_test ();
+ simple_subpool_test (0, 0);
+ create_delete_test ();
+ cleanup_fn_test ();
+ cleanup_fd_test ();
+ cleanup_malloc_test ();
+ lots_of_pmalloc_test ();
+}
+
+/* The tracing code. */
+#undef malloc
+#undef realloc
+#undef free
+
+static int nr_allocations = 0;
+
+static void
+trace_init ()
+{
+}
+
+static void
+trace_finish ()
+{
+ if (nr_allocations > 0)
+ {
+ fprintf (stderr, "*** error: %d allocation(s) leaked.\n",
+ nr_allocations);
+ exit (1);
+ }
+}
+
+static void *
+trace_malloc (size_t n, const char *filename, int line)
+{
+ nr_allocations++;
+ return malloc (n);
+}
+
+static void *
+trace_realloc (void *p, size_t n, const char *filename, int line)
+{
+ return realloc (p, n);
+}
+
+static void
+trace_free (void *p)
+{
+ nr_allocations--;
+ free (p);
+}
--- /dev/null
+/* Test pre library.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_pre.c,v 1.1 2002/10/05 16:42:06 rich Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <pcre.h>
+
+#include "pool.h"
+#include "vector.h"
+#include "pstring.h"
+#include "pre.h"
+
+static int vequals (vector v, int i, const char *str);
+
+int
+main ()
+{
+ pool pool;
+ vector v;
+ pcre *re1, *re2, *re3, *re4, *re5;
+ const char *str;
+
+ pool = new_subpool (global_pool);
+
+ /* Compile some regular expressions. */
+ re1 = precomp (pool, "a*b+", 0);
+ re2 = precomp (pool, "bu(t+)ery", 0);
+ re3 = precomp (pool, "m(a+)rgar(ee+)ne", 0);
+ re4 = precomp (pool, "(a|b)(c|d)+", 0);
+ re5 = precomp (pool, "(a|b)((c|d)+)", 0);
+
+ /* Matching tests. */
+ v = prematch (pool, "", re1, 0);
+ assert (v == 0);
+
+ v = prematch (pool, "a", re1, 0);
+ assert (v == 0);
+
+ v = prematch (pool, "ab", re1, 0);
+ assert (v);
+ assert (vector_size (v) == 1);
+ assert (vequals (v, 0, "ab"));
+
+ v = prematch (pool, "b", re1, 0);
+ assert (v);
+ assert (vector_size (v) == 1);
+ assert (vequals (v, 0, "b"));
+
+ v = prematch (pool, "xxxaaaaaaaaaabby", re1, 0);
+ assert (v);
+ assert (vector_size (v) == 1);
+ assert (vequals (v, 0, "aaaaaaaaaabb"));
+
+ v = prematch (pool, "This is quite buttery.", re2, 0);
+ assert (v);
+ assert (vector_size (v) == 2);
+ assert (vequals (v, 0, "buttery"));
+ assert (vequals (v, 1, "tt"));
+
+ v = prematch (pool, "This is quite buttttttery.", re2, 0);
+ assert (v);
+ assert (vector_size (v) == 2);
+ assert (vequals (v, 0, "buttttttery"));
+ assert (vequals (v, 1, "tttttt"));
+
+ v = prematch (pool, "margarene", re3, 0);
+ assert (v == 0);
+
+ v = prematch (pool, "margareene", re3, 0);
+ assert (v);
+ assert (vector_size (v) == 3);
+ assert (vequals (v, 0, "margareene"));
+ assert (vequals (v, 1, "a"));
+ assert (vequals (v, 2, "ee"));
+
+ v = prematch (pool, "maargareeene", re3, 0);
+ assert (v);
+ assert (vector_size (v) == 3);
+ assert (vequals (v, 0, "maargareeene"));
+ assert (vequals (v, 1, "aa"));
+ assert (vequals (v, 2, "eee"));
+
+ v = prematch (pool, "abcd", re4, 0);
+ assert (v);
+ assert (vector_size (v) == 3);
+ assert (vequals (v, 0, "bcd"));
+ assert (vequals (v, 1, "b"));
+ assert (vequals (v, 2, "d"));
+
+ v = prematch (pool, "abcd", re5, 0);
+ assert (v);
+ assert (vector_size (v) == 4);
+ assert (vequals (v, 0, "bcd"));
+ assert (vequals (v, 1, "b"));
+ assert (vequals (v, 2, "cd"));
+ assert (vequals (v, 3, "d"));
+
+ /* Substitution tests. */
+
+ str = presubst (pool, "xxxxmaargareeeeneyy", re3, "$1$2", 0);
+ assert (strcmp (str, "xxxxaaeeeeyy") == 0);
+
+ str = presubst (pool, "xxxxmaargareeeeneyy", re3, "$2$1", 0);
+ assert (strcmp (str, "xxxxeeeeaayy") == 0);
+
+ str = presubst (pool, "xxxxmaargareeeeneyy xxxxmaargareeeeneyy",
+ re3, "$2$1", 0);
+ assert (strcmp (str, "xxxxeeeeaayy xxxxmaargareeeeneyy") == 0);
+
+ str = presubst (pool, "abcd", re4, "$2$1", 0);
+ assert (strcmp (str, "adb") == 0);
+
+ /* Check all the presubst flags work correctly. */
+ str = presubst (pool, "xxxxmaargareeeeneyy", re3, "$1$2",
+ PRESUBST_NO_PLACEHOLDERS);
+ assert (strcmp (str, "xxxx$1$2yy") == 0);
+
+ str = presubst (pool, "This is buttery buttery toast.", re2, "tasty",
+ PRESUBST_GLOBAL);
+ assert (strcmp (str, "This is tasty tasty toast.") == 0);
+
+ delete_pool (pool);
+ exit (0);
+}
+
+static int
+vequals (vector v, int i, const char *str)
+{
+ const char *s;
+
+ vector_get (v, i, s);
+ return strcmp (s, str) == 0;
+}
--- /dev/null
+/* Test pstring library.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_pstring.c,v 1.11 2003/02/09 16:48:46 rich Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <pcre.h>
+
+#include "pstring.h"
+#include "vector.h"
+
+const int i_one = 1, i_two = 2, i_three = 3, i_four = 4,
+ i_15 = 15, i_31 = 31, i_63 = 63, i_127 = 127;
+const double d_one = 1, d_two = 2, d_three = 3, d_four = 4;
+const char *s_one = "one", *s_two = "two", *s_three = "three",
+ *s_four = "four";
+
+const char *stra[] = { "one", "two", "three", "four" };
+
+const char *file1[] = { "line1\r\n",
+ "line2\r\n",
+ "line3\r\n", 0};
+const char *file2[] = { "line1\n",
+ "line2\n",
+ "line3\n", 0 };
+const char *file3[] = { "line1\n",
+ "line2\n",
+ "\n",
+ "line3\n", 0 };
+const char *file4[] = { "line1\\\n",
+ "line2\n",
+ "line3\n", 0 };
+const char *file5[] = { "line1\n",
+ "# a comment\n",
+ "line2\n",
+ "line3\n", 0 };
+const char *res1[] = { "line1", "line2", "line3", 0 };
+const char *res2[] = { "line1line2", "line3", 0 };
+
+static int
+my_strcmp (const char **p1, const char **p2)
+{
+ return strcmp (*p1, *p2);
+}
+
+int
+main ()
+{
+ pool pool;
+ char *s1, *s2;
+ vector v1, v2, v3, v4, v5;
+ pcre *re;
+ int i;
+ FILE *fp;
+ const char **sp;
+ const char *errptr;
+ int erroffset;
+
+ pool = new_pool ();
+
+ /* pstrdup */
+ s1 = pstrdup (pool, "sheep");
+ s2 = pstrdup (pool, s1);
+
+ s1[1] = 'l';
+
+ assert (strcmp (s2, "sheep") == 0);
+
+ /* pstrndup */
+ s1 = pstrndup (pool, "sheep", 3);
+ s2 = pstrndup (pool, "sheep", 6);
+
+ assert (strcmp (s1, "she") == 0);
+ assert (strcmp (s2, "sheep") == 0);
+
+ /* pmemdup */
+ s1 = pmemdup (pool, "waves", 6);
+
+ assert (strcmp (s1, "waves") == 0);
+
+ /* pstrsplit */
+ v1 = pstrsplit (pool, "one", "--");
+ v2 = pstrsplit (pool, "--one--two", "--");
+ v3 = pstrsplit (pool, "one--two--three", "--");
+ v4 = pstrsplit (pool, "one--two--three--four--", "--");
+
+ v5 = new_vector (pool, char *);
+ vector_push_back (v5, s_one);
+ assert (vector_compare (v1, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_two);
+ assert (vector_compare (v2, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_three);
+ assert (vector_compare (v3, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_four);
+ assert (vector_compare (v4, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+
+ /* pstrcsplit */
+ v1 = pstrcsplit (pool, "one", ',');
+ v2 = pstrcsplit (pool, ",one,two", ',');
+ v3 = pstrcsplit (pool, "one,two,three,", ',');
+ v4 = pstrcsplit (pool, "one,two,three,four", ',');
+
+ v5 = new_vector (pool, char *);
+ vector_push_back (v5, s_one);
+ assert (vector_compare (v1, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_two);
+ assert (vector_compare (v2, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_three);
+ assert (vector_compare (v3, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_four);
+ assert (vector_compare (v4, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+
+ /* pstrresplit */
+ re = pcre_compile ("[ \t]+", 0, &errptr, &erroffset, 0);
+ assert (re);
+ v1 = pstrresplit (pool, "one", re);
+ v2 = pstrresplit (pool, " one \ttwo", re);
+ v3 = pstrresplit (pool, " one\ttwo\tthree ", re);
+ v4 = pstrresplit (pool, " one two \t three four ", re);
+
+ v5 = new_vector (pool, char *);
+ vector_push_back (v5, s_one);
+ assert (vector_compare (v1, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_two);
+ assert (vector_compare (v2, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_three);
+ assert (vector_compare (v3, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ vector_push_back (v5, s_four);
+ assert (vector_compare (v4, v5, (int (*)(const void *,const void *))my_strcmp) == 0);
+ free (re);
+
+ /* pconcat, pjoin */
+ v1 = new_vector (pool, char *);
+ vector_push_back (v1, s_one);
+ vector_push_back (v1, s_two);
+ vector_push_back (v1, s_three);
+ vector_push_back (v1, s_four);
+ s1 = pconcat (pool, v1);
+ assert (strcmp (s1, "onetwothreefour") == 0);
+ s1 = pjoin (pool, v1, "");
+ assert (strcmp (s1, "onetwothreefour") == 0);
+ s1 = pjoin (pool, v1, ",");
+ assert (strcmp (s1, "one,two,three,four") == 0);
+ s1 = pjoin (pool, v1, ", ");
+ assert (strcmp (s1, "one, two, three, four") == 0);
+
+ /* pstrresplit2 -> pconcat = original string */
+ re = pcre_compile ("[ \t]+", 0, &errptr, &erroffset, 0);
+ s1 = "the quick brown fox";
+ v1 = pstrresplit2 (pool, s1, re);
+ s2 = pconcat (pool, v1);
+ assert (strcmp (s1, s2) == 0);
+
+ s1 = " the quick \tbrown fox";
+ v1 = pstrresplit2 (pool, s1, re);
+ s2 = pconcat (pool, v1);
+ assert (strcmp (s1, s2) == 0);
+
+ s1 = "the quick brown \tfox\t";
+ v1 = pstrresplit2 (pool, s1, re);
+ s2 = pconcat (pool, v1);
+ assert (strcmp (s1, s2) == 0);
+
+ s1 = " \tthe quick brown \tfox\t";
+ v1 = pstrresplit2 (pool, s1, re);
+ s2 = pconcat (pool, v1);
+ assert (strcmp (s1, s2) == 0);
+ free (re);
+
+ /* psort */
+ v1 = new_vector (pool, char *);
+ vector_push_back (v1, s_one);
+ vector_push_back (v1, s_two);
+ vector_push_back (v1, s_three);
+ vector_push_back (v1, s_four);
+ psort (v1, my_strcmp);
+ s1 = pconcat (pool, v1);
+ assert (strcmp (s1, "fouronethreetwo") == 0);
+
+ /* pchomp */
+ s1 = pstrdup (pool, "sheep");
+ pchomp (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "sheep\r");
+ pchomp (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "sheep\r\n");
+ pchomp (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "sheep\n");
+ pchomp (s1);
+ assert (strcmp (s1, "sheep") == 0);
+
+ /* pchrs, pstrs */
+ s1 = pchrs (pool, 'x', 20);
+ assert (strcmp (s1, "xxxxxxxxxxxxxxxxxxxx") == 0);
+ s1 = pchrs (pool, 'x', 0);
+ assert (strcmp (s1, "") == 0);
+ s1 = pstrs (pool, "x", 20);
+ assert (strcmp (s1, "xxxxxxxxxxxxxxxxxxxx") == 0);
+ s1 = pstrs (pool, "xyz", 10);
+ assert (strcmp (s1, "xyzxyzxyzxyzxyzxyzxyzxyzxyzxyz") == 0);
+ s1 = pstrs (pool, "xyz", 0);
+ assert (strcmp (s1, "") == 0);
+ s1 = pstrs (pool, "", 100);
+ assert (strcmp (s1, "") == 0);
+
+ /* psprintf (also implicitly tests pvsprintf) */
+ s1 = psprintf (pool, "%d %s %s %s %s",
+ 4, "one", "two", "three", "four");
+ assert (strcmp (s1, "4 one two three four") == 0);
+ for (i = 250; i < 270; ++i)
+ {
+ s1 = pchrs (pool, 'x', i);
+ s2 = psprintf (pool, "%s", s1);
+ assert (strcmp (s1, s2) == 0);
+ }
+
+ /* pvector, pvectora */
+ s1 = pjoin (pool, pvector (pool, "one", "two", "three", "four", 0), ",");
+ assert (strcmp (s1, "one,two,three,four") == 0);
+ s1 = pjoin (pool, pvectora (pool, stra, 4), ",");
+ assert (strcmp (s1, "one,two,three,four") == 0);
+
+ /* pitoa, pdtoa, pxtoa */
+ assert (strcmp (pitoa (pool, 1), "1") == 0);
+ assert (strcmp (pdtoa (pool, 2.1), "2.100000") == 0);
+ assert (strcmp (pxtoa (pool, 15), "f") == 0);
+
+ /* pvitostr, pvdtostr, pvxtostr */
+ v1 = new_vector (pool, int);
+ vector_push_back (v1, i_one);
+ vector_push_back (v1, i_two);
+ vector_push_back (v1, i_three);
+ vector_push_back (v1, i_four);
+ s1 = pjoin (pool, pvitostr (pool, v1), ",");
+ assert (strcmp (s1, "1,2,3,4") == 0);
+
+ v1 = new_vector (pool, double);
+ vector_push_back (v1, d_one);
+ vector_push_back (v1, d_two);
+ vector_push_back (v1, d_three);
+ vector_push_back (v1, d_four);
+ s1 = pjoin (pool, pvdtostr (pool, v1), ",");
+ assert (strcmp (s1, "1.000000,2.000000,3.000000,4.000000") == 0);
+
+ v1 = new_vector (pool, unsigned);
+ vector_push_back (v1, i_15);
+ vector_push_back (v1, i_31);
+ vector_push_back (v1, i_63);
+ vector_push_back (v1, i_127);
+ s1 = pjoin (pool, pvxtostr (pool, v1), ",");
+ assert (strcmp (s1, "f,1f,3f,7f") == 0);
+
+ /* pstrcat */
+ s1 = pstrdup (pool, "one");
+ s1 = pstrcat (pool, s1, ",two");
+ assert (strcmp (s1, "one,two") == 0);
+
+ /* pstrncat */
+ s1 = pstrdup (pool, "one");
+ s1 = pstrncat (pool, s1, ",two,three", 4);
+ assert (strcmp (s1, "one,two") == 0);
+
+ /* psubstr */
+ s1 = psubstr (pool, "sheep", 1, 2);
+ assert (strcmp (s1, "he") == 0);
+ s1 = psubstr (pool, "sheep", 1, -1);
+ assert (strcmp (s1, "heep") == 0);
+
+ /* pstrupr, pstrlwr */
+ s1 = pstrdup (pool, "sheep");
+ pstrupr (s1);
+ assert (strcmp (s1, "SHEEP") == 0);
+ pstrlwr (s1);
+ assert (strcmp (s1, "sheep") == 0);
+
+ /* pgetline, pgetlinex, pgetlinec */
+#define TEST_PGETL(getfn,input,expect) s1 = pstrdup (pool, ""); fp = tmpfile (); for (sp = input; *sp; ++sp) fputs (*sp, fp); rewind (fp); for (sp = expect; *sp; ++sp) { s1 = getfn (pool, fp, s1); assert (strcmp (s1, *sp) == 0); } assert (getfn (pool, fp, s1) == 0); fclose (fp);
+
+ TEST_PGETL (pgetline, file1, res1);
+ TEST_PGETL (pgetline, file2, res1);
+ TEST_PGETL (pgetlinec, file3, res1);
+ TEST_PGETL (pgetlinec, file4, res2);
+ TEST_PGETL (pgetlinec, file5, res1);
+
+ /* ptrim, ptrimfront, ptrimback */
+ s1 = pstrdup (pool, " sheep\t\t\t");
+ ptrim (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "sheep ");
+ ptrim (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, " sheep");
+ ptrim (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "sheep");
+ ptrim (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "");
+ ptrim (s1);
+ assert (strcmp (s1, "") == 0);
+
+ s1 = pstrdup (pool, " sheep");
+ ptrimfront (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "sheep ");
+ ptrimfront (s1);
+ assert (strcmp (s1, "sheep ") == 0);
+ s1 = pstrdup (pool, "sheep");
+ ptrimfront (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "");
+ ptrimfront (s1);
+ assert (strcmp (s1, "") == 0);
+
+ s1 = pstrdup (pool, " sheep");
+ ptrimback (s1);
+ assert (strcmp (s1, " sheep") == 0);
+ s1 = pstrdup (pool, "sheep ");
+ ptrimback (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "sheep");
+ ptrimback (s1);
+ assert (strcmp (s1, "sheep") == 0);
+ s1 = pstrdup (pool, "");
+ ptrimback (s1);
+ assert (strcmp (s1, "") == 0);
+
+ delete_pool (pool);
+ exit (0);
+}
--- /dev/null
+/* Test the sash (string hash) class.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_sash.c,v 1.1 2001/02/08 12:51:32 rich Exp $
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <pool.h>
+#include <vector.h>
+#include <pstring.h>
+#include <hash.h>
+
+int
+main ()
+{
+ sash h;
+ pool pool = new_pool (), pool2;
+ const char *v;
+ vector keys, values;
+
+ /* Create a string -> string hash. */
+ h = new_sash (pool);
+
+ /* Insert some new values. */
+ if (sash_insert (h, "tomato", "red") != 0) abort ();
+ if (sash_insert (h, "orange", "orange") != 0) abort ();
+ if (sash_insert (h, "lemon", "yellow") != 0) abort ();
+ if (sash_insert (h, "lime", "green") != 0) abort ();
+ if (sash_insert (h, "peach", "orange") != 0) abort ();
+ if (sash_insert (h, "apple", "green") != 0) abort ();
+ if (sash_insert (h, "raspberry", "red") != 0) abort ();
+
+ /* This should replace existing values. */
+ if (sash_insert (h, "apple", "red") == 0) abort ();
+ if (sash_insert (h, "peach", "yellow") == 0) abort ();
+
+ /* Retrieve some values. */
+ if (sash_get (h, "apple", v) == 0 || strcmp (v, "red") != 0) abort ();
+ if (sash_get (h, "tomato", v) == 0 || strcmp (v, "red") != 0) abort ();
+ if (sash_get (h, "orange", v) == 0 || strcmp (v, "orange") != 0) abort ();
+
+ /* Copy the sash. */
+ h = copy_sash (pool, h);
+
+ /* Erase a key and check that it no longer exists. */
+ if (sash_erase (h, "apple") == 0) abort ();
+ if (sash_get (h, "apple", v) != 0) abort ();
+
+ /* Get list of keys and values. */
+ keys = sash_keys (h);
+ values = sash_values (h);
+
+ printf ("keys = [ %s ]\n", pjoin (pool, keys, ", "));
+ printf ("values = [ %s ]\n", pjoin (pool, values, ", "));
+
+ /* Copy the sash into another pool, delete the old pool, check all
+ * keys and values have been copied across.
+ */
+ pool2 = new_pool ();
+ h = copy_sash (pool2, h);
+ delete_pool (pool);
+
+ keys = sash_keys (h);
+ values = sash_values (h);
+
+ printf ("keys = [ %s ]\n", pjoin (pool2, keys, ", "));
+ printf ("values = [ %s ]\n", pjoin (pool2, values, ", "));
+
+ delete_pool (pool2);
+ exit (0);
+}
--- /dev/null
+/* Test the shash (string -> something hash) class.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_shash.c,v 1.2 2002/08/23 09:44:08 rich Exp $
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <pool.h>
+#include <vector.h>
+#include <pstring.h>
+#include <hash.h>
+
+const int red = 1, orange = 2, yellow = 3, green = 4;
+
+int
+main ()
+{
+ shash h;
+ pool pool = new_pool (), pool2, tmp;
+ int v;
+ vector keys, values;
+
+ /* Create a string -> string hash. */
+ h = new_shash (pool, int);
+
+ /* Insert some new values. */
+ if (shash_insert (h, "tomato", red) != 0) abort ();
+ if (shash_insert (h, "orange", orange) != 0) abort ();
+ if (shash_insert (h, "lemon", yellow) != 0) abort ();
+ if (shash_insert (h, "lime", green) != 0) abort ();
+ if (shash_insert (h, "peach", orange) != 0) abort ();
+ if (shash_insert (h, "apple", green) != 0) abort ();
+ if (shash_insert (h, "raspberry", red) != 0) abort ();
+
+ /* This should replace existing values. */
+ if (shash_insert (h, "apple", red) == 0) abort ();
+ if (shash_insert (h, "peach", yellow) == 0) abort ();
+
+ /* Retrieve some values. */
+ if (shash_get (h, "apple", v) == 0 || v != red) abort ();
+ if (shash_get (h, "tomato", v) == 0 || v != red) abort ();
+ if (shash_get (h, "orange", v) == 0 || v != orange) abort ();
+
+ /* Copy the shash. */
+ h = copy_shash (pool, h);
+
+ /* Erase a key and check that it no longer exists. */
+ if (shash_erase (h, "apple") == 0) abort ();
+ if (shash_get (h, "apple", v) != 0) abort ();
+
+ /* Get list of keys and values. */
+ keys = shash_keys (h);
+ values = shash_values (h);
+
+ printf ("keys = [ %s ]\n", pjoin (pool, keys, ", "));
+ printf ("values = [ %s ]\n", pjoin (pool, pvitostr (pool, values), ", "));
+
+ /* Regression test: get list of keys into another temporary pool. */
+ tmp = new_pool ();
+ keys = shash_keys_in_pool (h, tmp);
+ printf ("keys = [ %s ]\n", pjoin (pool, keys, ", "));
+ delete_pool (tmp);
+
+ /* Copy the shash into another pool, delete the old pool, check all
+ * keys and values have been copied across.
+ */
+ pool2 = new_pool ();
+ h = copy_shash (pool2, h);
+ delete_pool (pool);
+
+ keys = shash_keys (h);
+ values = shash_values (h);
+
+ printf ("keys = [ %s ]\n", pjoin (pool2, keys, ", "));
+ printf ("values = [ %s ]\n", pjoin (pool2, pvitostr (pool2, values), ", "));
+
+ delete_pool (pool2);
+ exit (0);
+}
--- /dev/null
+/* Test the tree class.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_tree.c,v 1.1 2002/09/15 15:08:52 rich Exp $
+ *
+ * XXX This test is incomplete.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#include "pool.h"
+#include "tree.h"
+
+int
+main ()
+{
+ pool pool1 = new_subpool (global_pool), pool2;
+ tree root, leaf1, leaf2, leaf3, t;
+ const char *root_node = "root node";
+ const char *leaf1_node = "leaf1 node";
+ const char *leaf2_node = "leaf2 node";
+ const char *leaf3_node = "leaf3 node";
+ char *str;
+
+ /* Create a simple node and test node access functions. */
+ root = new_tree (pool1, char *);
+
+ tree_set_data (root, root_node);
+
+ leaf1 = new_tree (pool1, char *);
+ tree_set_data (leaf1, leaf1_node);
+ leaf2 = new_tree (pool1, char *);
+ tree_set_data (leaf2, leaf2_node);
+ leaf3 = new_tree (pool1, char *);
+ tree_set_data (leaf3, leaf3_node);
+ tree_push_back (root, leaf1);
+ tree_push_back (root, leaf2);
+ tree_push_back (root, leaf3);
+
+ assert (tree_size (root) == 3);
+
+ tree_get (root, 0, t);
+ assert (t == leaf1);
+ tree_get (root, 1, t);
+ assert (t == leaf2);
+ tree_get (root, 2, t);
+ assert (t == leaf3);
+
+ tree_pop_front (root, t);
+ assert (t == leaf1);
+ tree_pop_back (root, t);
+ assert (t == leaf3);
+ tree_pop_front (root, t);
+ assert (t == leaf2);
+
+ assert (tree_size (root) == 0);
+
+ tree_insert (root, 0, leaf1);
+ tree_insert (root, 1, leaf2);
+ tree_insert (root, 2, leaf3);
+
+ tree_get (root, 0, t);
+ assert (t == leaf1);
+ tree_get (root, 1, t);
+ assert (t == leaf2);
+ tree_get (root, 2, t);
+ assert (t == leaf3);
+
+ tree_replace (root, 0, leaf3);
+ tree_replace (root, 1, leaf1);
+ tree_replace (root, 2, leaf2);
+
+ tree_get (root, 0, t);
+ assert (t == leaf3);
+ tree_get (root, 1, t);
+ assert (t == leaf1);
+ tree_get (root, 2, t);
+ assert (t == leaf2);
+
+ tree_erase (root, 0);
+ assert (tree_size (root) == 2);
+
+ tree_erase_range (root, 0, 2);
+ assert (tree_size (root) == 0);
+
+ tree_insert (root, 0, leaf1);
+ tree_insert (root, 1, leaf2);
+ tree_insert (root, 2, leaf3);
+
+ tree_clear (root);
+ assert (tree_size (root) == 0);
+
+ tree_get_data (root, str);
+ assert (strcmp (str, root_node) == 0);
+
+ /* Copy the tree into another pool, delete the original. */
+ tree_insert (root, 0, leaf1);
+ tree_insert (root, 1, leaf2);
+ tree_insert (root, 2, leaf3);
+
+ pool2 = new_subpool (global_pool);
+ root = copy_tree (pool2, root);
+ delete_pool (pool1);
+
+ assert (tree_size (root) == 3);
+
+ tree_get_data (root, str);
+ assert (strcmp (str, root_node) == 0);
+
+ tree_get (root, 0, t);
+ tree_get_data (t, str);
+ assert (strcmp (str, leaf1_node) == 0);
+
+ tree_get (root, 1, t);
+ tree_get_data (t, str);
+ assert (strcmp (str, leaf2_node) == 0);
+
+ tree_get (root, 2, t);
+ tree_get_data (t, str);
+ assert (strcmp (str, leaf3_node) == 0);
+
+ exit (0);
+}
--- /dev/null
+/* Test the vector class.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: test_vector.c,v 1.2 2001/02/16 12:55:54 rich Exp $
+ *
+ * XXX This test is very incomplete at present.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#include <pool.h>
+#include <vector.h>
+#include <pstring.h>
+
+/* These are the numbers we'll be inserting into the array. */
+static int numbers1to9[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+static void sqr_ptr (int *a, int *r) { *r = *a * *a; }
+static int gt20_ptr (int *a) { return *a > 20; }
+
+int
+main ()
+{
+ pool pool = new_pool ();
+ vector numbers, squares, squaresgt20;
+
+ /* Create initial vector. */
+ numbers = new_vector (pool, int);
+ vector_insert_array (numbers, 0, numbers1to9, 9);
+ assert (vector_size (numbers) == 9);
+
+ /* Print numbers. */
+ printf ("numbers = [ %s ]\n",
+ pjoin (pool, pvitostr (pool, numbers), ", "));
+
+ /* Square each number. */
+ squares = vector_map (pool, numbers,
+ (void (*) (const void *, void *)) sqr_ptr,
+ int);
+ assert (vector_size (squares) == 9);
+ printf ("squares = [ %s ]\n",
+ pjoin (pool, pvitostr (pool, squares), ", "));
+
+ /* Get squares > 20. */
+ squaresgt20 = vector_grep (pool, squares,
+ (int (*) (const void *)) gt20_ptr);
+ assert (vector_size (squaresgt20) == 5);
+ printf ("squares > 20 = [ %s ]\n",
+ pjoin (pool, pvitostr (pool, squaresgt20), ", "));
+
+ delete_pool (pool);
+ exit (0);
+}
--- /dev/null
+#!/usr/bin/perl -w
+
+# Show current allocations from a trace file. If run over a trace file
+# from a program which has exited, this will show memory leaks. If run
+# over a trace file for a program which is currently running, this will
+# show currently allocated space.
+#
+# By Richard W.M. Jones <rich@annexia.org>
+#
+# $Id: curallocs.pl,v 1.1 2001/02/08 12:51:35 rich Exp $
+
+use strict;
+
+my %pools = ();
+
+my $lineno = 0;
+
+while (<>)
+ {
+ $lineno++;
+
+ s/[\n\r]+$//;
+
+ if (/^([a-z_]+)\s+caller:\s+([0-9a-fx]+)\s+ptr1:\s+([0-9a-fx]+|\(nil\))\s+ptr2:\s+([0-9a-fx]+|\(nil\))\s+ptr3:\s+([0-9a-fx]+|\(nil\))\s+i1:\s+([0-9]+)\s*$/)
+ {
+ my $fn = $1;
+ my $caller = $2;
+ my $ptr1 = $3 ne '(nil)' ? $3 : 0;
+ my $ptr2 = $4 ne '(nil)' ? $4 : 0;
+ my $ptr3 = $5 ne '(nil)' ? $4 : 0;
+ my $i1 = $6;
+
+ if ($fn eq "new_pool")
+ {
+ die "new_pool: pool exists, line $lineno"
+ if exists $pools{$ptr1};
+
+ $pools{$ptr1} = {
+ creator => $caller,
+ pool => $ptr1,
+ children => {},
+ allocations => {}
+ };
+ }
+ elsif ($fn eq "new_subpool")
+ {
+ die "new_subpool: pool exists, line $lineno"
+ if exists $pools{$ptr1};
+
+ $pools{$ptr1} = {
+ creator => $caller,
+ pool => $ptr1,
+ parent => $ptr2,
+ children => {},
+ allocations => {}
+ };
+ $pools{$ptr2}{children}{$ptr1} = 1;
+ }
+ elsif ($fn eq "delete_pool")
+ {
+ if ($pools{$ptr1}{parent})
+ {
+ delete $pools{$pools{$ptr1}{parent}}{children}{$ptr1};
+ }
+
+ remove_pool_recursively ($ptr1);
+ }
+ elsif ($fn eq "pmalloc")
+ {
+ die "pmalloc: no pool $ptr1, line $lineno"
+ unless exists $pools{$ptr1};
+
+ $pools{$ptr1}{allocations}{$ptr2} = {
+ creator => $caller,
+ pool => $ptr1,
+ address => $ptr2,
+ size => $i1
+ };
+ }
+ elsif ($fn eq "prealloc")
+ {
+ die "prealloc: no pool $ptr1, line $lineno"
+ unless exists $pools{$ptr1};
+ die "prealloc: allocation already exists, line $lineno"
+ unless exists $pools{$ptr1}{allocations}{$ptr2};
+
+ # Delete the old allocation.
+ delete $pools{$ptr1}{allocations}{$ptr2};
+
+ $pools{$ptr1}{allocations}{$ptr3} = {
+ creator => $caller,
+ pool => $ptr1,
+ address => $ptr3,
+ size => $i1
+ };
+ }
+ else
+ {
+ die "unknown pool function traced: $fn, line $lineno";
+ }
+ }
+ else
+ {
+ print "$lineno: $_\n";
+ die "cannot parse line";
+ }
+ }
+
+if (keys %pools > 0) {
+ show_pools ();
+} else {
+ print "No pools are currently allocated.\n";
+}
+
+exit 0;
+
+sub remove_pool_recursively
+ {
+ my $pool = shift;
+ local $_;
+
+ die unless exists $pools{$pool};
+
+ # Remove children first.
+ foreach (keys %{$pools{$pool}{children}})
+ {
+ remove_pool_recursively ($_);
+ }
+
+ delete $pools{$pool};
+ }
+
+sub show_pools
+ {
+ local $_;
+
+ foreach (keys %pools)
+ {
+ show_pool ($_);
+ }
+ }
+
+sub show_pool
+ {
+ my $pool = shift;
+ my $indent = shift || 0;
+ local $_;
+
+ my $sp = " " x $indent;
+
+ print $sp, "pool $pool created by $pools{$pool}{creator}:\n";
+ print $sp, " number of direct allocations: ", 0 + keys %{$pools{$pool}{allocations}}, "\n";
+ print $sp, " number of children: ", 0 + keys %{$pools{$pool}{children}}, "\n";
+ print $sp, " allocations:\n";
+
+ show_allocations ($pools{$pool}{allocations}, $indent);
+
+ print $sp, " children:\n";
+
+ foreach (keys %{$pools{$pool}{children}})
+ {
+ show_pool ($_, $indent + 2);
+ }
+ }
+
+sub show_allocations
+ {
+ my $allocations = shift;
+ my $indent = shift || 0;
+ local $_;
+
+ foreach (keys %$allocations)
+ {
+ show_allocation ($allocations->{$_}, $indent);
+ }
+ }
+
+sub show_allocation
+ {
+ my $allocation = shift;
+ my $indent = shift || 0;
+ local $_;
+
+ my $sp = " " x $indent;
+
+ print $sp, " allocation $allocation->{address} created by $allocation->{creator} size $allocation->{size}\n";
+ }
--- /dev/null
+/* A tree class.
+ * - By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: tree.c,v 1.2 2002/10/08 15:10:28 rich Exp $
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <pool.h>
+#include <vector.h>
+#include <pstring.h>
+
+#include "tree.h"
+
+tree
+_tree_new (pool pool, size_t size)
+{
+ tree t = (tree) new_vector (pool, tree);
+
+ t = prealloc (pool, t, sizeof (*t) + size);
+ t->size = size;
+
+ return t;
+}
+
+extern tree
+copy_tree (pool pool, tree t)
+{
+ tree nt = _tree_new (pool, t->size);
+ int i;
+
+ /* Copy the node data. */
+ memcpy (nt->data, t->data, t->size);
+
+ /* Copy each subnode, recursively. */
+ for (i = 0; i < tree_size (t); ++i)
+ {
+ tree st, nst;
+
+ tree_get (t, i, st);
+ nst = copy_tree (pool, st);
+ tree_push_back (nt, nst);
+ }
+
+ return nt;
+}
+
+void
+_tree_get_data (tree t, void *ptr)
+{
+ if (ptr) memcpy (ptr, t->data, t->size);
+}
+
+void
+_tree_set_data (tree t, const void *ptr)
+{
+ if (ptr) memcpy (t->data, ptr, t->size);
+}
--- /dev/null
+/* A tree class.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: tree.h,v 1.1 2002/09/15 15:08:52 rich Exp $
+ */
+
+#ifndef TREE_H
+#define TREE_H
+
+#include <pool.h>
+#include <vector.h>
+
+struct tree
+{
+ struct vector v; /* Vector of subnodes. */
+ size_t size; /* Size of the data. */
+ char data[0]; /* Opaque data (used by the application). */
+};
+
+typedef struct tree *tree;
+
+/* Function: new_tree - allocate a new tree, node or leaf
+ * Function: _tree_new
+ *
+ * Allocate a new tree / node / leaf.
+ *
+ * A node in the tree is defined as a list of pointers to subnodes
+ * and some data stored in the node itself. Because of the recursive
+ * definition of trees, a tree is just a node, the special 'root'
+ * node. A leaf is just a node which happens to have no subnodes. You
+ * can add subnodes to a leaf later if you want.
+ *
+ * The @code{new_vector} macro is used to allocate a node in the
+ * tree storing data @code{type} in the node. It just evaluates the
+ * size of @code{type} and calls @code{_tree_new} which actually
+ * allocates the node.
+ *
+ * Unless you are very careful with types, you should always make
+ * sure that each node in your tree has the same @code{type}.
+ *
+ * Returns: The tree / node (of type @code{tree}).
+ */
+#define new_tree(pool,type) _tree_new ((pool), sizeof (type))
+extern tree _tree_new (pool, size_t size);
+
+/* Function: tree_get_data - access the data stored in a node
+ * Function: _tree_get_data
+ * Function: tree_set_data
+ * Function: _tree_set_data
+ *
+ * These functions allow you to access the data stored in the node.
+ *
+ * @code{tree_get_data} copies the data out of the node into the
+ * local variable.
+ *
+ * @code{tree_set_data} copies the data from the local variable into
+ * the node.
+ */
+#define tree_get_data(t,obj) _tree_get_data ((t), &(obj))
+extern void _tree_get_data (tree t, void *ptr);
+#define tree_set_data(t,obj) _tree_set_data ((t), &(obj))
+extern void _tree_set_data (tree t, const void *ptr);
+
+/* Function: copy_tree - make a deep copy of a tree
+ *
+ * Make a deep copy of tree @code{t} into pool @code{pool}. This
+ * copies all of the nodes and the data in those nodes recursively
+ * Note however that if the data in a node is a / contains a pointer
+ * then the pointed-to data will not be copied.
+ *
+ * Returns: The copied tree (of type @code{tree}).
+ */
+extern tree copy_tree (pool, tree t);
+
+/* Function: tree_push_back - add or remove subnodes to or from a node
+ * Function: tree_pop_back
+ * Function: tree_push_front
+ * Function: tree_pop_front
+ *
+ * The @code{*_push_*} functions push subnodes into nodes.
+ *
+ * The @code{*_pop_*} functions pop subnodes off nodes into local variables.
+ *
+ * The @code{*_front} functions push and pop subnodes off the front
+ * of a node.
+ *
+ * The @code{*_back} functions push and pop subnodes
+ * off the end of the node.
+ *
+ * Array indexes are checked. You cannot pop a node which has
+ * no subnodes.
+ */
+#define tree_push_back(t,subnode) (vector_push_back ((vector)(t), (subnode)))
+#define tree_pop_back(t,subnode) (vector_pop_back ((vector)(t), (subnode)))
+#define tree_push_front(t,subnode) (vector_push_front ((vector)(t), (subnode)))
+#define tree_pop_front(t,subnode) (vector_pop_front ((vector)(t), (subnode)))
+
+/* Function: tree_get_subnode - get a particular subnode of a node
+ * Function: tree_get
+ *
+ * @code{tree_get_subnode} returns the @code{i}th subnode of a node. The
+ * node is unaffected.
+ *
+ * @code{tree_get} is identical.
+ */
+#define tree_get_subnode(t,i,subnode) tree_get((t), (i), (subnode))
+#define tree_get(t,i,subnode) (vector_get ((vector)(t), (i), (subnode)))
+
+/* Function: tree_insert - insert subnodes into a tree
+ * Function: tree_insert_array
+ *
+ * @code{tree_insert} inserts a single subnode @code{subnode} before subnode
+ * @code{i}. All other subnodes are moved up to make space.
+ *
+ * @code{tree_insert_array} inserts an array of @code{n} subnodes
+ * starting at address @code{ptr} into the node before index
+ * @code{i}.
+ *
+ * Array indexes are checked.
+ */
+#define tree_insert(t,i,subnode) (vector_insert ((vector)(t), (i), (subnode)))
+#define tree_insert_array(t,i,ptr,n) (vector_insert_array ((vector)(t), (i), (ptr), (n)))
+
+/* Function: tree_replace - replace subnodes of a node
+ * Function: tree_replace_array
+ *
+ * @code{tree_replace} replaces the single subnode at
+ * @code{v[i]} with @code{subnode}.
+ *
+ * @code{tree_replace_array} replaces the @code{n} subnodes
+ * in the node starting at index @code{i} with the @code{n}
+ * subnodes from the array @code{ptr}.
+ *
+ * Array indexes are checked.
+ */
+#define tree_replace(t,i,subnode) (vector_replace ((vector)(t), (i), (subnode)))
+#define tree_replace_array(t,i,ptr,n) (vector_replace_array ((vector)(t), (i), (ptr), (n)))
+
+/* Function: tree_erase - erase subnodes of a node
+ * Function: tree_erase_range
+ * Function: tree_clear
+ *
+ * @code{tree_erase} removes the subnode index @code{i}, shuffling
+ * the later subnodes down by one place to fill the space.
+ *
+ * @code{tree_erase_range} removes a range of subnodes @code{i}
+ * to @code{j-1} (@code{i <= j}), shuffling later subnodes down
+ * to fill the space.
+ *
+ * @code{tree_clear} removes all subnodes from the node, setting
+ * its size to @code{0}, and effectively making the node into a leaf.
+ *
+ * Array indexes are checked.
+ */
+#define tree_erase(t,i) (vector_erase ((vector)(t), (i)))
+#define tree_erase_range(t,i,j) (vector_erase_range ((vector)(t), (i), (j)))
+#define tree_clear(t) (vector_clear ((vector)(t)))
+
+/* Function: tree_size - return the number of subnodes of a node
+ * Function: tree_nr_subnodes
+ *
+ * Return the size (ie. number of subnodes) in the node. The
+ * @code{tree_nr_subnodes} macro is identical.
+ */
+#define tree_size(t) (vector_size ((vector)(t)))
+#define tree_nr_subnodes(t) tree_size(t)
+
+/* Function: tree_swap - swap the order of two subnodes of a node
+ *
+ * Swap subnodes @code{i} and @code{j} of tree @code{t}.
+ */
+#define tree_swap(t,i,j) (vector_swap ((vector)(t), (i), (j)))
+
+#endif /* TREE_H */
--- /dev/null
+/* A vector class.
+ * - By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: vector.c,v 1.4 2002/10/27 16:04:42 rich Exp $
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#include <pstring.h>
+#include <pool.h>
+#include <vector.h>
+
+#define INCREMENT 16
+
+vector
+_vector_new (pool pool, size_t size)
+{
+ vector v = pmalloc (pool, sizeof *v);
+
+ v->pool = pool;
+ v->size = size;
+ v->data = 0;
+ v->used = v->allocated = 0;
+
+ return v;
+}
+
+inline vector
+new_subvector (pool pool, vector v, int i, int j)
+{
+ vector new_v = pmalloc (pool, sizeof *v);
+
+ assert (0 <= i && j <= v->used);
+
+ new_v->pool = pool;
+ new_v->size = v->size;
+
+ if (i < j)
+ {
+ new_v->data = pmemdup (pool, v->data + i * v->size, (j - i) * v->size);
+ new_v->used = new_v->allocated = j - i;
+ }
+ else
+ {
+ new_v->data = 0;
+ new_v->used = new_v->allocated = 0;
+ }
+
+ return new_v;
+}
+
+vector
+copy_vector (pool pool, vector v)
+{
+ return new_subvector (pool, v, 0, v->used);
+}
+
+inline void
+_vector_push_back (vector v, const void *ptr)
+{
+ if (v->used >= v->allocated)
+ {
+ int a = v->allocated + INCREMENT;
+ void *d = prealloc (v->pool, v->data, a * v->size);
+ v->allocated = a;
+ v->data = d;
+ }
+
+ if (ptr) memcpy (v->data + v->used * v->size, ptr, v->size);
+ v->used++;
+}
+
+void
+_vector_pop_back (vector v, void *ptr)
+{
+ assert (v->used > 0);
+ v->used--;
+ if (ptr) memcpy (ptr, v->data + v->used * v->size, v->size);
+}
+
+inline void
+vector_insert_array (vector v, int i, const void *ptr, int n)
+{
+ int j;
+
+ assert (0 <= i && i <= v->used);
+
+ /* Insert n dummy elements at the end of the list. */
+ for (j = 0; j < n; ++j) _vector_push_back (v, 0);
+
+ /* Move the other elements up. */
+ for (j = v->used-1; j > i; --j)
+ memcpy (v->data + j * v->size, v->data + (j-n) * v->size, v->size);
+
+ /* Insert these elements at position i. */
+ if (ptr) memcpy (v->data + i * v->size, ptr, v->size * n);
+}
+
+void
+_vector_insert (vector v, int i, const void *ptr)
+{
+ vector_insert_array (v, i, ptr, 1);
+}
+
+void
+_vector_push_front (vector v, const void *ptr)
+{
+ _vector_insert (v, 0, ptr);
+}
+
+void
+_vector_pop_front (vector v, void *ptr)
+{
+ _vector_get (v, 0, ptr);
+ vector_erase (v, 0);
+}
+
+void
+vector_push_back_vector (vector v, const vector w)
+{
+ int size = v->size;
+
+ assert (size == w->size);
+
+ if (v->used + w->used > v->allocated)
+ {
+ int a = v->used + w->used;
+ void *d = prealloc (v->pool, v->data, a * size);
+ v->allocated = a;
+ v->data = d;
+ }
+
+ memcpy (v->data + v->used * size, w->data, size * w->used);
+ v->used += w->used;
+}
+
+void
+vector_push_front_vector (vector v, const vector w)
+{
+ int size = v->size;
+
+ assert (size == w->size);
+
+ if (v->used + w->used > v->allocated)
+ {
+ int a = v->used + w->used;
+ void *d = prealloc (v->pool, v->data, a * size);
+ v->allocated = a;
+ v->data = d;
+ }
+
+ memmove (v->data + w->used * size, v->data, v->used * size);
+ memcpy (v->data, w->data, size * w->used);
+ v->used += w->used;
+}
+
+void
+_vector_replace (vector v, int i, const void *ptr)
+{
+ assert (0 <= i && i < v->used);
+
+ if (ptr) memcpy (v->data + i * v->size, ptr, v->size);
+}
+
+inline void
+vector_erase_range (vector v, int i, int j)
+{
+ assert (0 <= i && i < v->used && 0 <= j && j <= v->used);
+
+ if (i < j)
+ {
+ int n = j - i, k;
+
+ for (k = i+n; k < v->used; ++k)
+ memcpy (v->data + (k-n) * v->size, v->data + k * v->size, v->size);
+
+ v->used -= n;
+ }
+}
+
+void
+vector_erase (vector v, int i)
+{
+ vector_erase_range (v, i, i+1);
+}
+
+void
+vector_clear (vector v)
+{
+ v->used = 0;
+}
+
+void
+_vector_get (vector v, int i, void *ptr)
+{
+ assert (0 <= i && i < v->used);
+ if (ptr) memcpy (ptr, v->data + i * v->size, v->size);
+}
+
+const void *
+_vector_get_ptr (vector v, int i)
+{
+ assert (0 <= i && i < v->used);
+ return v->data + i * v->size;
+}
+
+void
+_vector_sort (vector v, int (*compare_fn) (const void *, const void *))
+{
+ qsort (v->data, v->used, v->size, compare_fn);
+}
+
+int
+_vector_compare (vector v1, vector v2,
+ int (*compare_fn) (const void *, const void *))
+{
+ int i, r;
+ void *p1, *p2;
+
+ if (vector_size (v1) < vector_size (v2)) return -1;
+ else if (vector_size (v1) > vector_size (v2)) return 1;
+
+ for (i = 0; i < vector_size (v1); ++i)
+ {
+ vector_get_ptr (v1, i, p1);
+ vector_get_ptr (v2, i, p2);
+
+ r = compare_fn (p1, p2);
+
+ if (r != 0) return r;
+ }
+
+ return 0;
+}
+
+void
+_vector_fill (vector v, const void *ptr, int n)
+{
+ while (n--)
+ _vector_push_back (v, ptr);
+}
+
+void
+vector_swap (vector v, int i, int j)
+{
+ void *pi, *pj;
+ char data[v->size];
+
+ if (i == j) return;
+
+ vector_get_ptr (v, i, pi);
+ vector_get_ptr (v, j, pj);
+
+ memcpy (data, pi, v->size);
+ memcpy (pi, pj, v->size);
+ memcpy (pj, data, v->size);
+}
+
+void
+vector_reallocate (vector v, int n)
+{
+ if (n > v->allocated)
+ {
+ void *d = prealloc (v->pool, v->data, n * v->size);
+ v->allocated = n;
+ v->data = d;
+ }
+}
+
+vector
+vector_grep (pool p, vector v, int (*match_fn) (const void *))
+{
+ vector nv = _vector_new (p, v->size);
+ int i;
+
+ for (i = 0; i < v->used; ++i)
+ if (match_fn (v->data + i * v->size))
+ _vector_push_back (nv, v->data + i * v->size);
+
+ return nv;
+}
+
+vector
+vector_grep_pool (pool p, vector v, int (*match_fn) (pool, const void *))
+{
+ vector nv = _vector_new (p, v->size);
+ int i;
+
+ for (i = 0; i < v->used; ++i)
+ if (match_fn (p, v->data + i * v->size))
+ _vector_push_back (nv, v->data + i * v->size);
+
+ return nv;
+}
+
+vector
+_vector_map (pool p, vector v,
+ void (*map_fn) (const void *, void *),
+ size_t result_size)
+{
+ vector nv = _vector_new (p, result_size);
+ int i;
+
+ vector_reallocate (nv, v->used);
+ nv->used = v->used;
+
+ for (i = 0; i < v->used; ++i)
+ map_fn (v->data + i * v->size, nv->data + i * nv->size);
+
+ return nv;
+}
+
+vector
+_vector_map_pool (pool p, vector v,
+ void (*map_fn) (pool, const void *, void *),
+ size_t result_size)
+{
+ vector nv = _vector_new (p, result_size);
+ int i;
+
+ vector_reallocate (nv, v->used);
+ nv->used = v->used;
+
+ for (i = 0; i < v->used; ++i)
+ map_fn (p, v->data + i * v->size, nv->data + i * nv->size);
+
+ return nv;
+}
--- /dev/null
+/* A vector class.
+ * By Richard W.M. Jones <rich@annexia.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: vector.h,v 1.4 2002/10/27 16:04:42 rich Exp $
+ */
+
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#include <pool.h>
+
+struct vector
+{
+ pool pool;
+ size_t size;
+ void *data;
+ int used, allocated;
+};
+
+typedef struct vector *vector;
+
+/* Function: new_vector - allocate a new vector
+ * Function: _vector_new
+ *
+ * Allocate a new vector in @code{pool} of type @code{type}. The
+ * first form is just a macro which evaluates the size of @code{type}.
+ * The second form creates a vector with elements of the given
+ * @code{size} directly.
+ */
+#define new_vector(pool,type) _vector_new ((pool), sizeof (type))
+extern vector _vector_new (pool, size_t size);
+
+/* Function: copy_vector - copy a vector
+ * Function: new_subvector
+ *
+ * Copy a vector @code{v} into pool @code{pool}. If the vector
+ * contains pointers, then this function will not copy the pointed-to
+ * data as well: you will need to copy this yourself if appropriate.
+ *
+ * @code{new_subvector} creates a copy of part of an existing vector.
+ * The new vector contains the @code{j-i} elements of the old vector
+ * starting at element number @code{i} and finishing at element number
+ * @code{j-1}.
+ */
+extern vector copy_vector (pool, vector v);
+extern vector new_subvector (pool, vector v, int i, int j);
+
+/* Function: vector_push_back - push and pop objects into and out of vectors
+ * Function: _vector_push_back
+ * Function: vector_pop_back
+ * Function: _vector_pop_back
+ * Function: vector_push_front
+ * Function: _vector_push_front
+ * Function: vector_pop_front
+ * Function: _vector_pop_front
+ *
+ * The @code{*_push_*} functions push objects onto vectors.
+ *
+ * The @code{*_pop_*} functions pop objects off vectors into local variables.
+ *
+ * The @code{*_front} functions push and pop objects off the front
+ * of a vector. This type of operation is not very efficient, because
+ * it involves moving all other elements of the vector up or down
+ * by one place.
+ *
+ * The @code{*_back} functions push and pop elements
+ * off the end of the vector, which is efficient.
+ *
+ * Each function has two forms: a macro version and an underlying
+ * function.
+ *
+ * Array indexes are checked. You cannot pop an empty vector. If
+ * @code{ptr} is @code{NULL} then the popped object is discarded.
+ */
+#define vector_push_back(v,obj) _vector_push_back((v),&(obj))
+extern void _vector_push_back (vector, const void *ptr);
+#define vector_pop_back(v,obj) _vector_pop_back((v),&(obj))
+extern void _vector_pop_back (vector, void *ptr);
+#define vector_push_front(v,obj) _vector_push_front((v),&(obj))
+extern void _vector_push_front (vector, const void *ptr);
+#define vector_pop_front(v,obj) _vector_pop_front((v),&(obj))
+extern void _vector_pop_front (vector, void *ptr);
+
+/* Function: vector_push_back_vector - push list of objects on to vector
+ * Function: vector_push_front_vector
+ *
+ * @code{vector_push_back_vector} appends the elements of vector
+ * @code{w} on to the end of vector @code{v}.
+ *
+ * @code{vector_push_front_vector} prepends the elements of vector
+ * @code{w} on to the front of vector @code{v}.
+ *
+ * In both cases, vector @code{w} is left unchanged.
+ *
+ * See also: @ref{vector_push_back(3)}, @ref{vector_push_front(3)}.
+ */
+extern void vector_push_back_vector (vector v, const vector w);
+extern void vector_push_front_vector (vector v, const vector w);
+
+/* Function: vector_get - array-style indexing for vectors
+ * Function: _vector_get
+ * Function: vector_get_ptr
+ * Function: _vector_get_ptr
+ *
+ * @code{vector_get} copies the element at index @code{v[i]} into
+ * local variable @code{obj}. The vector is unaffected.
+ *
+ * @code{_vector_get} copies the element into the memory pointed
+ * to by @code{ptr}. If @code{ptr} is @code{NULL} then the effect
+ * is simply to check that element @code{v[i]} exists.
+ *
+ * @code{vector_get_ptr} and @code{_vector_get_ptr} are used to
+ * get a pointer to an element in the vector. This pointer actually
+ * points to the vector's internal data array. It is only valid
+ * as long as the user does not cause the internal data array to
+ * be reallocated or moved - typically this can happen when the
+ * user performs some operation which inserts more elements into
+ * the array.
+ *
+ * Array indexes are checked. An attempt to access an out-of-bounds
+ * element will result in a call to @ref{abort(3)}.
+ */
+#define vector_get(v,i,obj) _vector_get((v),(i),&(obj))
+extern void _vector_get (vector, int i, void *ptr);
+#define vector_get_ptr(v,i,ptr) (ptr) =((typeof (ptr))_vector_get_ptr((v),(i)))
+extern const void *_vector_get_ptr (vector, int i);
+
+/* Function: vector_insert - insert elements into a vector
+ * Function: _vector_insert
+ * Function: vector_insert_array
+ *
+ * @code{vector_insert} inserts a single object @code{obj} before element
+ * @code{i}. All other elements are moved up to make space.
+ *
+ * @code{vector_insert_array} inserts an array of @code{n} objects
+ * starting at address @code{ptr} into the vector before index
+ * @code{i}.
+ *
+ * Array indexes are checked.
+ */
+#define vector_insert(v,i,obj) _vector_insert((v),(i),&(obj))
+extern void _vector_insert (vector, int i, const void *ptr);
+extern void vector_insert_array (vector v, int i, const void *ptr, int n);
+
+/* Function: vector_replace - replace elements of a vector
+ * Function: _vector_replace
+ * Function: vector_replace_array
+ *
+ * @code{vector_replace} replaces the single element at
+ * @code{v[i]} with object @code{obj}.
+ *
+ * @code{vector_replace_array} replaces the @code{n} elements
+ * in the vector starting at index @code{i} with the @code{n}
+ * elements from the array @code{ptr}.
+ *
+ * Array indexes are checked.
+ */
+#define vector_replace(v,i,obj) _vector_replace((v),(i),&(obj))
+extern void _vector_replace (vector, int i, const void *ptr);
+extern void vector_replace_array (vector v, int i, const void *ptr, int n);
+
+/* Function: vector_erase - erase elements of a vector
+ * Function: vector_erase_range
+ * Function: vector_clear
+ *
+ * @code{vector_erase} removes the element @code{v[i]}, shuffling
+ * the later elements down by one place to fill the space.
+ *
+ * @code{vector_erase_range} removes a range of elements @code{v[i]}
+ * to @code{v[j-1]} (@code{i <= j}), shuffling later elements down
+ * to fill the space.
+ *
+ * @code{vector_clear} removes all elements from the vector, setting
+ * its size to @code{0}.
+ *
+ * Array indexes are checked.
+ */
+extern void vector_erase (vector v, int i);
+extern void vector_erase_range (vector v, int i, int j);
+extern void vector_clear (vector v);
+
+/* Function: vector_fill - fill a vector with identical elements
+ * Function: _vector_fill
+ *
+ * @code{vector_fill} appends @code{n} identical copies of
+ * @code{obj} to the vector. It is equivalent to calling
+ * @ref{vector_push_back(3)} in a loop @code{n} times.
+ */
+#define vector_fill(v,obj,n) _vector_fill((v),&(obj),(n))
+extern void _vector_fill (vector, const void *ptr, int n);
+
+/* Function: vector_size - return the size of a vector
+ *
+ * Return the size (ie. number of elements) in the vector.
+ */
+#define vector_size(v) ((v)->used)
+
+/* Function: vector_allocated - return the space allocated to a vector
+ *
+ * Return the amount of space which has been allocated for storing
+ * elements of the vector. This is different from the number of
+ * elements actually stored by the vector (see @ref{vector_size(3)})
+ * and also different from the size of each element in bytes
+ * (see @ref{vector_element_size(3)}).
+ */
+#define vector_allocated(v) ((v)->allocated)
+
+/* Function: vector_element_size - return the size of each element of a vector
+ *
+ * Return the size in bytes of each element in vector.
+ */
+#define vector_element_size(v) ((v)->size)
+
+/* Function: vector_reallocate - change allocation for a vector
+ *
+ * Increase the amount of space allocated to a vector. See also
+ * @ref{vector_allocated(3)}. This function can be used to avoid
+ * the vector itself making too many calls to the underlying
+ * @ref{prealloc(3)}, particularly if you know in advance exactly
+ * how many elements the vector will contain.
+ */
+extern void vector_reallocate (vector v, int n);
+
+/* Function: vector_grep - produce a new vector containing elements of the old vector which match a boolean function
+ *
+ * This macro calls @code{match_fn(&t)} for each element @code{t} of
+ * vector @code{v}. It constructs and returns a new vector containing
+ * all those elements where the function returns true.
+ */
+extern vector vector_grep (pool, vector v, int (*match_fn) (const void *));
+
+/* Function: vector_grep_pool - produce a new vector containing elements of the old vector which match a boolean function
+ *
+ * This macro calls @code{match_fn(pool, &t)} for each element @code{t} of
+ * vector @code{v}. It constructs and returns a new vector containing
+ * all those elements where the function returns true.
+ */
+extern vector vector_grep_pool (pool, vector v, int (*match_fn) (pool, const void *));
+
+/* Function: vector_map - apply function to each element of a vector
+ * Function: _vector_map
+ *
+ * Call @code{map_fn(&t, &r)} for each element @code{t} of vector @code{v}.
+ * The result (@code{r}) should have type @code{result_type}
+ * and these are concatenated to form a new vector which is returned.
+ */
+#define vector_map(pool,v,map_fn,result_type) _vector_map ((pool), (v), (map_fn), sizeof (result_type))
+extern vector _vector_map (pool, vector v, void (*map_fn) (const void *, void *), size_t result_size);
+
+/* Function: vector_map_pool - apply function to each element of a vector
+ * Function: _vector_map_pool
+ *
+ * Call @code{map_fn(pool, &t, &r)} for each element @code{t} of vector
+ * @code{v}. The result (@code{r}) should have type @code{result_type}
+ * and these are concatenated to form a new vector which is returned.
+ */
+#define vector_map_pool(pool,v,map_fn,result_type) _vector_map_pool ((pool), (v), (map_fn), sizeof (result_type))
+extern vector _vector_map_pool (pool, vector v, void (*map_fn_pool) (pool, const void *, void *), size_t result_size);
+
+/* Function: vector_sort - sort a vector in-place
+ * Function: _vector_sort
+ *
+ * Sort a vector in-place, comparing elements using @code{compare_fn}.
+ */
+#define vector_sort(v,compare_fn) _vector_sort ((v), (int (*)(const void *,const void *)) (compare_fn))
+extern void _vector_sort (vector v, int (*compare_fn) (const void *, const void *));
+
+/* Function: vector_compare - compare two vectors
+ * Function: _vector_compare
+ *
+ * Compare two vectors. This returns 0 if the two vectors are
+ * identical. It returns > 0 if @code{v1} > @code{v2}. This
+ * returns < 0 if @code{v1} < @code{v2}.
+ */
+#define vector_compare(v1,v2,compare_fn) _vector_compare ((v1), (v2), (int (*)(const void *,const void *)) (compare_fn))
+extern int _vector_compare (vector, vector, int (*compare_fn) (const void *, const void *));
+
+/* Function: vector_reverse - reverse the elements of a vector in-place
+ *
+ * Reverse the elements of a vector in-place.
+ */
+extern void vector_reverse (vector v);
+
+/* Function: vector_swap - swap two elements of a vector
+ *
+ * Swap elements @code{i} and @code{j} of vector @code{v}.
+ */
+extern void vector_swap (vector v, int i, int j);
+
+#endif /* VECTOR_H */