initial load of upstream version 1.06.32 master
authorReto Zingg <rzingg@laptop.localdomain>
Tue, 7 Apr 2009 19:54:49 +0000 (22:54 +0300)
committerReto Zingg <rzingg@laptop.localdomain>
Tue, 7 Apr 2009 19:54:49 +0000 (22:54 +0300)
408 files changed:
.cvsignore [new file with mode: 0644]
GNUmakefile [new file with mode: 0644]
Makefile [new file with mode: 0644]
Makefile.common [new file with mode: 0644]
Makefile.config.in [new file with mode: 0644]
Makefile.depend [new file with mode: 0644]
README [new file with mode: 0644]
Windows/.cvsignore [new file with mode: 0644]
Windows/ConfigureWin32.bat [new file with mode: 0644]
Windows/ReadMeWin32.txt [new file with mode: 0644]
Windows/UsingCURLinWin32.txt [new file with mode: 0644]
Windows/abyss.dsp [new file with mode: 0644]
Windows/all.dsp [new file with mode: 0644]
Windows/all.vcproj [new file with mode: 0644]
Windows/configwin32.dsp [new file with mode: 0644]
Windows/configwin32.vcproj [new file with mode: 0644]
Windows/cpptest.dsp [new file with mode: 0644]
Windows/cpptest.vcproj [new file with mode: 0644]
Windows/query_meerkat.dsp [new file with mode: 0644]
Windows/query_meerkat.vcproj [new file with mode: 0644]
Windows/rpctest.dsp [new file with mode: 0644]
Windows/rpctest.vcproj [new file with mode: 0644]
Windows/transport_config_win32.h [new file with mode: 0644]
Windows/win32_config.h [new file with mode: 0644]
Windows/xmlrpc.dsp [new file with mode: 0644]
Windows/xmlrpc.dsw [new file with mode: 0644]
Windows/xmlrpc.sln [new file with mode: 0644]
Windows/xmlrpc.vcproj [new file with mode: 0644]
Windows/xmlrpc_sample_add_asynch_client.dsp [new file with mode: 0644]
Windows/xmlrpc_sample_add_asynch_client.vcproj [new file with mode: 0644]
Windows/xmlrpc_sample_add_server.dsp [new file with mode: 0644]
Windows/xmlrpc_sample_add_server.vcproj [new file with mode: 0644]
Windows/xmlrpc_sample_add_server_w32httpsys.dsp [new file with mode: 0644]
Windows/xmlrpc_sample_add_server_w32httpsys.vcproj [new file with mode: 0644]
Windows/xmlrpc_sample_add_sync_client.dsp [new file with mode: 0644]
Windows/xmlrpc_sample_add_sync_client.vcproj [new file with mode: 0644]
Windows/xmlrpc_sample_auth_client.dsp [new file with mode: 0644]
Windows/xmlrpc_sample_auth_client.vcproj [new file with mode: 0644]
Windows/xmlrpc_win32_config.h [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
autom4te.cache/output.0 [new file with mode: 0644]
autom4te.cache/requests [new file with mode: 0644]
autom4te.cache/traces.0 [new file with mode: 0644]
conf/abyss_root/conf/abyss.conf [new file with mode: 0644]
conf/abyss_root/conf/mime.types [new file with mode: 0644]
conf/abyss_root/htdocs/index.htm [new file with mode: 0644]
conf/abyss_root/htdocs/pwrabyss.gif [new file with mode: 0644]
config.guess [new file with mode: 0755]
config.sub [new file with mode: 0755]
configure [new file with mode: 0755]
configure.in [new file with mode: 0644]
doc/COPYING [new file with mode: 0644]
doc/CREDITS [new file with mode: 0644]
doc/DEVELOPING [new file with mode: 0644]
doc/HISTORY [new file with mode: 0644]
doc/INSTALL [new file with mode: 0644]
doc/SECURITY [new file with mode: 0644]
doc/TESTING [new file with mode: 0644]
doc/TODO [new file with mode: 0644]
doc/configure_doc [new file with mode: 0644]
examples/.cvsignore [new file with mode: 0644]
examples/Makefile [new file with mode: 0644]
examples/README [new file with mode: 0644]
examples/auth_client.c [new file with mode: 0644]
examples/cpp/.cvsignore [new file with mode: 0644]
examples/cpp/Makefile [new file with mode: 0644]
examples/cpp/meerkat-app-list.cpp [new file with mode: 0644]
examples/cpp/sample_add_client_complex.cpp [new file with mode: 0644]
examples/cpp/xmlrpc_inetd_server.cpp [new file with mode: 0644]
examples/cpp/xmlrpc_loop_server.cpp [new file with mode: 0644]
examples/cpp/xmlrpc_sample_add_client.cpp [new file with mode: 0644]
examples/cpp/xmlrpc_sample_add_server.cpp [new file with mode: 0644]
examples/gen_sample_add_xml.c [new file with mode: 0644]
examples/query-meerkat.c [new file with mode: 0644]
examples/synch_client.c [new file with mode: 0644]
examples/xmlrpc_asynch_client.c [new file with mode: 0644]
examples/xmlrpc_inetd_server.c [new file with mode: 0644]
examples/xmlrpc_loop_server.c [new file with mode: 0644]
examples/xmlrpc_sample_add_client.c [new file with mode: 0644]
examples/xmlrpc_sample_add_server.c [new file with mode: 0644]
examples/xmlrpc_sample_add_server_cgi.c [new file with mode: 0644]
examples/xmlrpc_sample_add_server_w32httpsys.c [new file with mode: 0644]
examples/xmlrpc_server_validatee.c [new file with mode: 0644]
examples/xmlrpc_socket_server.c [new file with mode: 0644]
include/Makefile [new file with mode: 0644]
include/xmlrpc-c/.cvsignore [new file with mode: 0644]
include/xmlrpc-c/abyss.h [new file with mode: 0644]
include/xmlrpc-c/base.h [new file with mode: 0644]
include/xmlrpc-c/base.hpp [new file with mode: 0644]
include/xmlrpc-c/base64.hpp [new file with mode: 0644]
include/xmlrpc-c/base_int.h [new file with mode: 0644]
include/xmlrpc-c/client.h [new file with mode: 0644]
include/xmlrpc-c/client.hpp [new file with mode: 0644]
include/xmlrpc-c/client_global.h [new file with mode: 0644]
include/xmlrpc-c/client_int.h [new file with mode: 0644]
include/xmlrpc-c/client_simple.hpp [new file with mode: 0644]
include/xmlrpc-c/client_transport.hpp [new file with mode: 0644]
include/xmlrpc-c/girerr.hpp [new file with mode: 0644]
include/xmlrpc-c/girmem.hpp [new file with mode: 0644]
include/xmlrpc-c/oldcppwrapper.hpp [new file with mode: 0644]
include/xmlrpc-c/oldxmlrpc.h [new file with mode: 0644]
include/xmlrpc-c/registry.hpp [new file with mode: 0644]
include/xmlrpc-c/server.h [new file with mode: 0644]
include/xmlrpc-c/server_abyss.h [new file with mode: 0644]
include/xmlrpc-c/server_abyss.hpp [new file with mode: 0644]
include/xmlrpc-c/server_cgi.h [new file with mode: 0644]
include/xmlrpc-c/server_w32httpsys.h [new file with mode: 0644]
include/xmlrpc-c/sleep_int.h [new file with mode: 0644]
include/xmlrpc-c/string_int.h [new file with mode: 0644]
include/xmlrpc-c/timeout.hpp [new file with mode: 0644]
include/xmlrpc-c/transport.h [new file with mode: 0644]
include/xmlrpc-c/util.h [new file with mode: 0644]
include/xmlrpc-c/util_int.h [new file with mode: 0644]
include/xmlrpc-c/xml.hpp [new file with mode: 0644]
include/xmlrpc-c/xmlparser.h [new file with mode: 0644]
install-sh [new file with mode: 0755]
lib/Makefile [new file with mode: 0644]
lib/Makefile.depend [new file with mode: 0644]
lib/abyss/Makefile [new file with mode: 0644]
lib/abyss/Makefile.depend [new file with mode: 0644]
lib/abyss/README [new file with mode: 0644]
lib/abyss/change.log [new file with mode: 0644]
lib/abyss/conf/abyss.conf [new file with mode: 0644]
lib/abyss/conf/mime.types [new file with mode: 0644]
lib/abyss/htdocs/index.htm [new file with mode: 0644]
lib/abyss/htdocs/pwrabyss.gif [new file with mode: 0644]
lib/abyss/license.txt [new file with mode: 0644]
lib/abyss/patch_notes.txt [new file with mode: 0644]
lib/abyss/readme.txt [new file with mode: 0644]
lib/abyss/src/Abyss.dsp [new file with mode: 0644]
lib/abyss/src/Abyss.dsw [new file with mode: 0644]
lib/abyss/src/Makefile [new file with mode: 0644]
lib/abyss/src/Makefile.depend [new file with mode: 0644]
lib/abyss/src/abyss_info.h [new file with mode: 0644]
lib/abyss/src/conf.c [new file with mode: 0644]
lib/abyss/src/conn.c [new file with mode: 0644]
lib/abyss/src/conn.h [new file with mode: 0644]
lib/abyss/src/data.c [new file with mode: 0644]
lib/abyss/src/data.h [new file with mode: 0644]
lib/abyss/src/date.c [new file with mode: 0644]
lib/abyss/src/date.h [new file with mode: 0644]
lib/abyss/src/file.c [new file with mode: 0644]
lib/abyss/src/file.h [new file with mode: 0644]
lib/abyss/src/http.c [new file with mode: 0644]
lib/abyss/src/http.h [new file with mode: 0644]
lib/abyss/src/main.c [new file with mode: 0644]
lib/abyss/src/response.c [new file with mode: 0644]
lib/abyss/src/server.c [new file with mode: 0644]
lib/abyss/src/server.h [new file with mode: 0644]
lib/abyss/src/session.c [new file with mode: 0644]
lib/abyss/src/session.h [new file with mode: 0644]
lib/abyss/src/socket.c [new file with mode: 0644]
lib/abyss/src/socket.h [new file with mode: 0644]
lib/abyss/src/socket_unix.c [new file with mode: 0644]
lib/abyss/src/socket_unix.h [new file with mode: 0644]
lib/abyss/src/socket_win.c [new file with mode: 0644]
lib/abyss/src/socket_win.h [new file with mode: 0644]
lib/abyss/src/thread.h [new file with mode: 0644]
lib/abyss/src/thread_fork.c [new file with mode: 0644]
lib/abyss/src/thread_pthread.c [new file with mode: 0644]
lib/abyss/src/thread_windows.c [new file with mode: 0644]
lib/abyss/src/token.c [new file with mode: 0644]
lib/abyss/src/token.h [new file with mode: 0644]
lib/abyss/src/trace.c [new file with mode: 0644]
lib/abyss/src/trace.h [new file with mode: 0644]
lib/abyss/version.txt [new file with mode: 0644]
lib/curl_transport/Makefile [new file with mode: 0644]
lib/curl_transport/Makefile.depend [new file with mode: 0644]
lib/curl_transport/xmlrpc_curl_transport.c [new file with mode: 0644]
lib/curl_transport/xmlrpc_curl_transport.h [new file with mode: 0644]
lib/expat/Makefile [new file with mode: 0644]
lib/expat/Makefile.depend [new file with mode: 0644]
lib/expat/expat.dsw [new file with mode: 0644]
lib/expat/expat.html [new file with mode: 0644]
lib/expat/gennmtab/.cvsignore [new file with mode: 0644]
lib/expat/gennmtab/Makefile [new file with mode: 0644]
lib/expat/gennmtab/Makefile.depend [new file with mode: 0644]
lib/expat/gennmtab/gennmtab.c [new file with mode: 0644]
lib/expat/gennmtab/gennmtab.dsp [new file with mode: 0644]
lib/expat/xmlparse/Makefile [new file with mode: 0644]
lib/expat/xmlparse/Makefile.depend [new file with mode: 0644]
lib/expat/xmlparse/xmlparse.c [new file with mode: 0644]
lib/expat/xmlparse/xmlparse.dsp [new file with mode: 0644]
lib/expat/xmlparse/xmlparse.h [new file with mode: 0644]
lib/expat/xmltok/.cvsignore [new file with mode: 0644]
lib/expat/xmltok/Makefile [new file with mode: 0644]
lib/expat/xmltok/Makefile.depend [new file with mode: 0644]
lib/expat/xmltok/ascii.h [new file with mode: 0644]
lib/expat/xmltok/asciitab.h [new file with mode: 0644]
lib/expat/xmltok/dllmain.c [new file with mode: 0644]
lib/expat/xmltok/iasciitab.h [new file with mode: 0644]
lib/expat/xmltok/latin1tab.h [new file with mode: 0644]
lib/expat/xmltok/utf8tab.h [new file with mode: 0644]
lib/expat/xmltok/xmldef.h [new file with mode: 0644]
lib/expat/xmltok/xmlrole.c [new file with mode: 0644]
lib/expat/xmltok/xmlrole.h [new file with mode: 0644]
lib/expat/xmltok/xmltok.c [new file with mode: 0644]
lib/expat/xmltok/xmltok.dsp [new file with mode: 0644]
lib/expat/xmltok/xmltok.h [new file with mode: 0644]
lib/expat/xmltok/xmltok_impl.c [new file with mode: 0644]
lib/expat/xmltok/xmltok_impl.h [new file with mode: 0644]
lib/expat/xmltok/xmltok_ns.c [new file with mode: 0644]
lib/expat/xmlwf/.cvsignore [new file with mode: 0644]
lib/expat/xmlwf/Makefile.in [new file with mode: 0644]
lib/expat/xmlwf/codepage.c [new file with mode: 0644]
lib/expat/xmlwf/codepage.h [new file with mode: 0644]
lib/expat/xmlwf/filemap.h [new file with mode: 0644]
lib/expat/xmlwf/readfilemap.c [new file with mode: 0644]
lib/expat/xmlwf/unixfilemap.c [new file with mode: 0644]
lib/expat/xmlwf/win32filemap.c [new file with mode: 0644]
lib/expat/xmlwf/xmlfile.c [new file with mode: 0644]
lib/expat/xmlwf/xmlfile.h [new file with mode: 0644]
lib/expat/xmlwf/xmltchar.h [new file with mode: 0644]
lib/expat/xmlwf/xmlwf.c [new file with mode: 0644]
lib/expat/xmlwf/xmlwf.dsp [new file with mode: 0644]
lib/libutil/Makefile [new file with mode: 0644]
lib/libutil/Makefile.depend [new file with mode: 0644]
lib/libutil/casprintf.c [new file with mode: 0644]
lib/libutil/error.c [new file with mode: 0644]
lib/libutil/make_printable.c [new file with mode: 0644]
lib/libutil/memblock.c [new file with mode: 0644]
lib/libutil/resource.c [new file with mode: 0644]
lib/libutil/sleep.c [new file with mode: 0644]
lib/libwww_transport/Makefile [new file with mode: 0644]
lib/libwww_transport/Makefile.depend [new file with mode: 0644]
lib/libwww_transport/xmlrpc_libwww_transport.c [new file with mode: 0644]
lib/libwww_transport/xmlrpc_libwww_transport.h [new file with mode: 0644]
lib/util/Makefile [new file with mode: 0644]
lib/util/Makefile.depend [new file with mode: 0644]
lib/util/casprintf.c [new file with mode: 0644]
lib/util/cmdline_parser.c [new file with mode: 0644]
lib/util/getoptx.c [new file with mode: 0644]
lib/util/getoptx.h [new file with mode: 0644]
lib/util/include/bool.h [new file with mode: 0644]
lib/util/include/c_util.h [new file with mode: 0644]
lib/util/include/casprintf.h [new file with mode: 0644]
lib/util/include/cmdline_parser.h [new file with mode: 0644]
lib/util/include/girmath.h [new file with mode: 0644]
lib/util/include/girstring.h [new file with mode: 0644]
lib/util/include/inline.h [new file with mode: 0644]
lib/util/include/linklist.h [new file with mode: 0644]
lib/util/include/mallocvar.h [new file with mode: 0644]
lib/util/include/pthreadx.h [new file with mode: 0644]
lib/util/include/unistdx.h [new file with mode: 0644]
lib/util/pthreadx_win32.c [new file with mode: 0644]
lib/wininet_transport/Makefile [new file with mode: 0644]
lib/wininet_transport/xmlrpc_wininet_transport.c [new file with mode: 0644]
lib/wininet_transport/xmlrpc_wininet_transport.h [new file with mode: 0644]
ltconfig [new file with mode: 0755]
ltmain.sh [new file with mode: 0644]
missing [new file with mode: 0755]
mkinstalldirs [new file with mode: 0755]
src/.cvsignore [new file with mode: 0644]
src/Makefile [new file with mode: 0644]
src/Makefile.depend [new file with mode: 0644]
src/cpp/Makefile [new file with mode: 0644]
src/cpp/Makefile.depend [new file with mode: 0644]
src/cpp/XmlRpcCpp.cpp [new file with mode: 0644]
src/cpp/base64.cpp [new file with mode: 0644]
src/cpp/client.cpp [new file with mode: 0644]
src/cpp/client_simple.cpp [new file with mode: 0644]
src/cpp/curl.cpp [new file with mode: 0644]
src/cpp/dll.make [new file with mode: 0644]
src/cpp/dylib.make [new file with mode: 0644]
src/cpp/env_wrap.cpp [new file with mode: 0644]
src/cpp/env_wrap.hpp [new file with mode: 0644]
src/cpp/fault.cpp [new file with mode: 0644]
src/cpp/girerr.cpp [new file with mode: 0644]
src/cpp/girmem.cpp [new file with mode: 0644]
src/cpp/irix.make [new file with mode: 0644]
src/cpp/libwww.cpp [new file with mode: 0644]
src/cpp/outcome.cpp [new file with mode: 0644]
src/cpp/param_list.cpp [new file with mode: 0644]
src/cpp/registry.cpp [new file with mode: 0644]
src/cpp/server_abyss.cpp [new file with mode: 0644]
src/cpp/test/.cvsignore [new file with mode: 0644]
src/cpp/test/Makefile [new file with mode: 0644]
src/cpp/test/Makefile.depend [new file with mode: 0644]
src/cpp/test/server_abyss.cpp [new file with mode: 0644]
src/cpp/test/server_abyss.hpp [new file with mode: 0644]
src/cpp/test/test.cpp [new file with mode: 0644]
src/cpp/test/testclient.cpp [new file with mode: 0644]
src/cpp/test/testclient.hpp [new file with mode: 0644]
src/cpp/test/testclient_dummy.cpp [new file with mode: 0644]
src/cpp/test/tools.cpp [new file with mode: 0644]
src/cpp/test/tools.hpp [new file with mode: 0644]
src/cpp/unix.make [new file with mode: 0644]
src/cpp/value.cpp [new file with mode: 0644]
src/cpp/wininet.cpp [new file with mode: 0644]
src/cpp/xml.cpp [new file with mode: 0644]
src/registry.c [new file with mode: 0644]
src/registry.h [new file with mode: 0644]
src/system_method.c [new file with mode: 0644]
src/system_method.h [new file with mode: 0644]
src/test/.cvsignore [new file with mode: 0644]
src/test/Makefile [new file with mode: 0644]
src/test/Makefile.depend [new file with mode: 0644]
src/test/cgi.c [new file with mode: 0644]
src/test/cgi.h [new file with mode: 0644]
src/test/cgitest1.c [new file with mode: 0644]
src/test/client.c [new file with mode: 0644]
src/test/client.h [new file with mode: 0644]
src/test/client_dummy.c [new file with mode: 0644]
src/test/data/req_no_params.xml [new file with mode: 0644]
src/test/data/req_out_of_order.xml [new file with mode: 0644]
src/test/data/req_value_name.xml [new file with mode: 0644]
src/test/data/sample_add_call.xml [new file with mode: 0644]
src/test/eftest_wrapper.sh [new file with mode: 0644]
src/test/http-req-simple.txt [new file with mode: 0644]
src/test/method_registry.c [new file with mode: 0644]
src/test/method_registry.h [new file with mode: 0644]
src/test/parse_xml.c [new file with mode: 0644]
src/test/parse_xml.h [new file with mode: 0644]
src/test/req_no_params.xml [new file with mode: 0644]
src/test/serialize.c [new file with mode: 0644]
src/test/serialize.h [new file with mode: 0644]
src/test/server_abyss.c [new file with mode: 0644]
src/test/server_abyss.h [new file with mode: 0644]
src/test/test.c [new file with mode: 0644]
src/test/test.h [new file with mode: 0644]
src/test/value.c [new file with mode: 0644]
src/test/value.h [new file with mode: 0644]
src/test/xml_data.c [new file with mode: 0644]
src/test/xml_data.h [new file with mode: 0644]
src/trace.c [new file with mode: 0644]
src/xmlrpc_array.c [new file with mode: 0644]
src/xmlrpc_authcookie.c [new file with mode: 0644]
src/xmlrpc_base64.c [new file with mode: 0644]
src/xmlrpc_builddecomp.c [new file with mode: 0644]
src/xmlrpc_client.c [new file with mode: 0644]
src/xmlrpc_client_global.c [new file with mode: 0644]
src/xmlrpc_data.c [new file with mode: 0644]
src/xmlrpc_datetime.c [new file with mode: 0644]
src/xmlrpc_expat.c [new file with mode: 0644]
src/xmlrpc_libxml2.c [new file with mode: 0644]
src/xmlrpc_parse.c [new file with mode: 0644]
src/xmlrpc_serialize.c [new file with mode: 0644]
src/xmlrpc_server_abyss.c [new file with mode: 0644]
src/xmlrpc_server_cgi.c [new file with mode: 0644]
src/xmlrpc_server_w32httpsys.c [new file with mode: 0644]
src/xmlrpc_struct.c [new file with mode: 0644]
src/xmlrpc_utf8.c [new file with mode: 0644]
stamp-h.in [new file with mode: 0644]
tools/.cvsignore [new file with mode: 0644]
tools/Makefile [new file with mode: 0644]
tools/Makefile.common [new file with mode: 0644]
tools/binmode-rpc-kit/COPYING [new file with mode: 0644]
tools/binmode-rpc-kit/Makefile [new file with mode: 0644]
tools/binmode-rpc-kit/README [new file with mode: 0644]
tools/binmode-rpc-kit/binmode-rpc-rfc.txt [new file with mode: 0644]
tools/binmode-rpc-kit/binmode-rpc2xml-rpc [new file with mode: 0755]
tools/binmode-rpc-kit/examples/good-1.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-1.xml [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-2.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-2.xml [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-3.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-3.xml [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-4.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-4.xml [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-5.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-5.xml [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-6.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/good-6.xml [new file with mode: 0644]
tools/binmode-rpc-kit/examples/invalid-1.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/invalid-2.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/invalid-3.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/invalid-4.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/examples/invalid-5.binmode [new file with mode: 0644]
tools/binmode-rpc-kit/oct2bin [new file with mode: 0755]
tools/interop-server/interop-cgi.c [new file with mode: 0644]
tools/turbocharger/.cvsignore [new file with mode: 0644]
tools/turbocharger/Makefile [new file with mode: 0644]
tools/turbocharger/README [new file with mode: 0644]
tools/turbocharger/mod_gzip.c [new file with mode: 0644]
tools/turbocharger/mod_gzip.c.diff [new file with mode: 0644]
tools/xml-rpc-api2cpp/.cvsignore [new file with mode: 0644]
tools/xml-rpc-api2cpp/DataType.cpp [new file with mode: 0644]
tools/xml-rpc-api2cpp/DataType.hpp [new file with mode: 0644]
tools/xml-rpc-api2cpp/Makefile [new file with mode: 0644]
tools/xml-rpc-api2cpp/Makefile.depend [new file with mode: 0644]
tools/xml-rpc-api2cpp/README [new file with mode: 0644]
tools/xml-rpc-api2cpp/SystemProxy.cpp [new file with mode: 0644]
tools/xml-rpc-api2cpp/SystemProxy.hpp [new file with mode: 0644]
tools/xml-rpc-api2cpp/XmlRpcClass.cpp [new file with mode: 0644]
tools/xml-rpc-api2cpp/XmlRpcClass.hpp [new file with mode: 0644]
tools/xml-rpc-api2cpp/XmlRpcFunction.cpp [new file with mode: 0644]
tools/xml-rpc-api2cpp/XmlRpcFunction.hpp [new file with mode: 0644]
tools/xml-rpc-api2cpp/xml-rpc-api2cpp.1 [new file with mode: 0644]
tools/xml-rpc-api2cpp/xml-rpc-api2cpp.cpp [new file with mode: 0644]
tools/xml-rpc-api2txt [new file with mode: 0755]
tools/xml-rpc-api2txt.1 [new file with mode: 0644]
tools/xmlrpc/.cvsignore [new file with mode: 0644]
tools/xmlrpc/Makefile [new file with mode: 0644]
tools/xmlrpc/Makefile.depend [new file with mode: 0644]
tools/xmlrpc/dumpvalue.c [new file with mode: 0644]
tools/xmlrpc/dumpvalue.h [new file with mode: 0644]
tools/xmlrpc/xmlrpc.c [new file with mode: 0644]
tools/xmlrpc/xmlrpc.html [new file with mode: 0644]
tools/xmlrpc_transport/.cvsignore [new file with mode: 0644]
tools/xmlrpc_transport/Makefile [new file with mode: 0644]
tools/xmlrpc_transport/Makefile.depend [new file with mode: 0644]
tools/xmlrpc_transport/xmlrpc_transport.c [new file with mode: 0644]
tools/xmlrpc_transport/xmlrpc_transport.html [new file with mode: 0644]
unix-common.make [new file with mode: 0644]
xmlrpc-c-config.in [new file with mode: 0644]
xmlrpc-c-config.test.in [new file with mode: 0644]
xmlrpc_amconfig.h.in [new file with mode: 0644]
xmlrpc_config.h.in [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..2e9a254
--- /dev/null
@@ -0,0 +1,17 @@
+Makefile.config
+autom4te.cache
+configure
+config.log
+stamp-h
+stamp-h1
+config.cache
+libtool
+config.status
+xmlrpc_config.h
+xmlrpc_amconfig.h
+xmlrpc-c-config
+xmlrpc-c-config.test
+xmlrpc-c.spec
+transport_config.h
+version.h
+
diff --git a/GNUmakefile b/GNUmakefile
new file mode 100644 (file)
index 0000000..0d5353c
--- /dev/null
@@ -0,0 +1,121 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)
+endif
+SUBDIR = .
+BUILDDIR = $(SRCDIR)
+VPATH = .:$(SRCDIR)
+
+include $(SRCDIR)/Makefile.config
+
+SUBDIRS = include lib src tools examples
+
+PROGRAMS_TO_INSTALL = xmlrpc-c-config
+
+# We're in a transition between the bloated, complex GNU
+# Autoconf/Automake style of build, in which 'configure' creates all
+# the make files, to simpler static make files.  Some directories have
+# been converted; some haven't.  So we have the hack of putting
+# 'xmlrpc_config.h' as the first dependency of 'all' to make sure
+# 'configure runs before anything in the case that the user neglects
+# to run 'configure' before doing 'make'.
+
+default: xmlrpc_config.h all
+
+.PHONY: all
+all: xmlrpc-c-config xmlrpc-c-config.test $(SUBDIRS:%=%/all)
+
+version.h: $(BUILDDIR)/Makefile.config
+       rm -f $@
+       echo '/* This file was generated by a make rule */' >>$@
+       echo '#define XMLRPC_C_VERSION "$(XMLRPC_C_VERSION)"' >>$@
+
+# We don't want Makefile.common's rule for version.h
+OMIT_VERSION_H = Y
+
+# We dont' want Makefile.common's rule for transport_config.h
+OMIT_TRANSPORT_CONFIG_H = Y
+
+transport_config.h: $(BUILDDIR)/Makefile.config
+       rm -f $@
+       echo '/* This file was generated by a make rule */' >>$@
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+       echo '#define MUST_BUILD_WININET_CLIENT 1' >>$@
+else
+       echo '#define MUST_BUILD_WININET_CLIENT 0' >>$@
+endif
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+       echo '#define MUST_BUILD_CURL_CLIENT 1' >>$@
+else
+       echo '#define MUST_BUILD_CURL_CLIENT 0' >>$@
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+       echo '#define MUST_BUILD_LIBWWW_CLIENT 1' >>$@
+else
+       echo '#define MUST_BUILD_LIBWWW_CLIENT 0' >>$@
+endif
+       echo "static const char * const XMLRPC_DEFAULT_TRANSPORT =" >>$@
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+       echo '"libwww";' >>$@
+else
+  ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+       echo '"curl";' >>$@
+  else
+    ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+       echo '"wininet";' >>$@
+    else
+       @echo 'ERROR: no client XML transport configured'; rm $@; false
+    endif
+  endif
+endif
+
+.PHONY: clean clean-local
+clean: $(SUBDIRS:%=%/clean) clean-common clean-local
+
+clean-local:
+       rm -f transport_config.h
+
+.PHONY: distclean distclean-local
+distclean: $(SUBDIRS:%=%/distclean) distclean-common distclean-local
+
+distclean-local: clean-local
+       rm -f config.log config.status Makefile.config libtool 
+       rm -f xmlrpc_config.h xmlrpc_amconfig.h stamp-h 
+       rm -f xmlrpc-c-config xmlrpc-c-config.test
+
+check: $(SUBDIRS:%=%/check)
+
+.PHONY: tags
+tags: $(SUBDIRS:%=%/tags) TAGS
+
+DISTFILES = 
+
+.PHONY: distdir
+distdir: distdir-common
+
+.PHONY: install
+install: $(SUBDIRS:%=%/install) install-common install-compat-hdr
+
+.PHONY: install-compat-hdr
+install-compat-hdr:
+# Install old names of header files for backward compatibility
+       cd $(DESTDIR)$(HEADERINST_DIR); \
+         rm -f xmlrpc.h xmlrpc_client.h xmlrpc_server.h xmlrpc_cgi.h \
+                xmlrpc_server_abyss.h xmlrpc_abyss.h \
+               xmlrpc_server_w32httpsys.h \
+               XmlRpcCpp.h; \
+         $(LN_S) xmlrpc-c/oldxmlrpc.h         xmlrpc.h; \
+         $(LN_S) xmlrpc-c/client.h            xmlrpc_client.h; \
+         $(LN_S) xmlrpc-c/server.h            xmlrpc_server.h; \
+         $(LN_S) xmlrpc-c/server_cgi.h        xmlrpc_cgi.h; \
+         $(LN_S) xmlrpc-c/server_abyss.h      xmlrpc_abyss.h; \
+         $(LN_S) xmlrpc-c/server_w32httpsys.h xmlrpc_server_w32httpsys.h; \
+         $(LN_S) xmlrpc-c/oldcppwrapper.hpp   XmlRpcCpp.h ;\
+
+.PHONY: dep
+dep: version.h $(BUILDDIR)/include/xmlrpc-c/config.h $(SUBDIRS:%=%/dep)
+
+xmlrpc-c-config xmlrpc-c-config.test xmlrpc_config.h xmlrpc_amconfig.h \
+       :%:%.in $(SRCDIR)/configure
+       $(SRCDIR)/configure
+
+include $(SRCDIR)/Makefile.common
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..af667d6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+# The make files for this package exploit features of GNU Make that
+# other Makes do not have.  Because it is a common mistake for users
+# to try to build with a different Make, we have this make file that
+# does nothing but tell the user to use GNU Make.
+
+# If the user were using GNU Make now, this file would not get used because
+# GNU Make uses a make file named "GNUmakefile" in preference to "Makefile"
+# if it exists.  This package contains a "GNUmakefile".
+
+all install clean dep depend:
+       @echo "You must use GNU Make to build this.  You are running some "
+       @echo "other Make.  GNU Make may be installed on your system with "
+       @echo "the name 'gmake'.  If not, see http://www.gnu.org/software ."
+       @echo
diff --git a/Makefile.common b/Makefile.common
new file mode 100644 (file)
index 0000000..342b35d
--- /dev/null
@@ -0,0 +1,452 @@
+# -*-makefile-*-    <-- an Emacs control
+
+# This file contains rules and variable settings for the convenience
+# of every other make file in the package.
+
+# No make file is required to use this file, but it usually saves a lot
+# of duplication.
+
+# The following make variables are meaningful as input to this file:
+#
+# SRCDIR:  Name of directory which is the top of the Xmlrpc-c source tree.
+# BUILDDIR: Name of directory which is the top of the Xmlrpc-c build tree.
+
+LIBTOOL = $(SRCDIR)/libtool
+LINK = $(LIBTOOL) --mode=link $(CCLD)
+
+GCC_WARNINGS = -Wall -Wundef -Wimplicit -W -Winline -Wundef
+  # We need -Wwrite-strings after we fix all the missing consts
+
+GCC_C_WARNINGS = $(GCC_WARNINGS) \
+  -Wmissing-declarations -Wstrict-prototypes -Wmissing-prototypes
+
+GCC_CXX_WARNINGS = $(GCC_WARNINGS) -Woverloaded-virtual -Wsynth
+
+# The NDEBUG macro says not to build code that assumes there are no bugs.
+# This makes the code go faster.  The main thing it does is tell the C library
+# to make assert() a no-op as opposed to generating code to check the
+# assertion and crash the program if it isn't really true.  You can add
+# -UNDEBUG (in any of various ways) to override this.
+#
+CFLAGS_COMMON = -DNDEBUG
+CXXFLAGS_COMMON = -DNDEBUG
+
+ifeq ($(C_COMPILER_GNU),yes)
+  CFLAGS_COMMON += $(GCC_C_WARNINGS) -fno-common -g -O3
+endif
+
+ifeq ($(CXX_COMPILER_GNU),yes)
+  CXXFLAGS_COMMON += $(GCC_CXX_WARNINGS) -g
+endif
+
+DISTDIR = $(BUILDDIR)/$(PACKAGE)-$(VERSION)/$(SUBDIR)
+
+# MAJ and MIN are major and minor version numbers for shared libraries.
+# Libtool builds are controlled by LDFLAGS_VERSINFO instead.
+MAJ = 3
+MIN = 06
+
+# LDFLAGS_VERSINFO is a libtool link option (--version-info) that
+# tells it what version numbers to put on the shared libraries (and
+# maybe in those special libtool link files).  Exactly how it works is
+# somewhat mysterious; it's designed to be part of a linking system
+# where you always use libtool to link the libraries, and libtool
+# figures out which if any version of a library meets the link's
+# requirements.  But we expect our libraries to be linked with the
+# regular (non-libtool) linker, so what we care about is the major,
+# minor, and revision numbers in the file names and sonames.  Libtool
+# has an option --version-number that supposedly lets us specify that,
+# but it doesn't seem to work.  All I get is 0.0.0.  So we manipulate
+# --version-info instead.
+#
+# This appears to work: in the option --version-info A.B.C:
+#
+#   C is the minor number
+#   B is the revision number
+#   A minus C is the major number.
+#
+# So you would get libxmlrpc.so.A-C.C.B .
+#
+# Our strategy is to make the library version numbers the same as the
+# Xmlrpc-c version numbers except that we update the major number when and
+# only when we make a non-backward-compatible change to the library.  So
+# e.g. libxmlrpc for Xmlrpc-c 1.06.01 is named libxmlrpc.so.3.6.1.
+
+LDFLAGS_VERSINFO = -version-info 9:15:6  # 3.6.15
+
+# CURDIR was introduced in GNU Make 3.77.
+ifeq ($(CURDIR)x,x)
+  CURDIR := $(shell /bin/pwd)
+endif
+
+LIBXMLRPC_UTIL           = $(BUILDDIR)/lib/libutil/libxmlrpc_util.la
+LIBXMLRPC                = $(BUILDDIR)/src/libxmlrpc.la
+LIBXMLRPC_CLIENT         = $(BUILDDIR)/src/libxmlrpc_client.la
+LIBXMLRPC_SERVER         = $(BUILDDIR)/src/libxmlrpc_server.la
+LIBXMLRPC_SERVER_ABYSS   = $(BUILDDIR)/src/libxmlrpc_server_abyss.la
+LIBXMLRPC_SERVER_CGI     = $(BUILDDIR)/src/libxmlrpc_server_cgi.la
+LIBXMLRPC_ABYSS          = $(BUILDDIR)/lib/abyss/src/libxmlrpc_abyss.la
+LIBXMLRPC_XMLPARSE       = $(BUILDDIR)/lib/expat/xmlparse/libxmlrpc_xmlparse.la
+LIBXMLRPC_XMLTOK         = $(BUILDDIR)/lib/expat/xmltok/libxmlrpc_xmltok.la
+LIBXMLRPC_UTIL_A         = $(BUILDDIR)/lib/libutil/.libs/libxmlrpc_util.a
+LIBXMLRPC_A              = $(BUILDDIR)/src/.libs/libxmlrpc.a
+LIBXMLRPC_CLIENT_A       = $(BUILDDIR)/src/.libs/libxmlrpc_client.a
+LIBXMLRPC_SERVER_A       = $(BUILDDIR)/src/.libs/libxmlrpc_server.a
+LIBXMLRPC_SERVER_ABYSS_A = $(BUILDDIR)/src/.libs/libxmlrpc_server_abyss.a
+LIBXMLRPC_SERVER_CGI_A   = $(BUILDDIR)/src/.libs/libxmlrpc_server_cgi.a
+LIBXMLRPC_ABYSS_A        = $(BUILDDIR)/lib/abyss/src/.libs/libxmlrpc_abyss.a
+LIBXMLRPC_XMLPARSE_A     = $(BUILDDIR)/lib/expat/xmlparse/.libs/libxmlrpc_xmlparse.a
+LIBXMLRPC_XMLTOK_A       = $(BUILDDIR)/lib/expat/xmltok/.libs/libxmlrpc_xmltok.a
+LIBXMLRPC_CPP            = $(BUILDDIR)/src/cpp/libxmlrpc_cpp.a
+LIBXMLRPC++              = $(BUILDDIR)/src/cpp/libxmlrpc++.a
+LIBXMLRPC_CLIENT++       = $(BUILDDIR)/src/cpp/libxmlrpc_client++.a
+LIBXMLRPC_SERVER++       = $(BUILDDIR)/src/cpp/libxmlrpc_server++.a
+LIBXMLRPC_SERVER_ABYSS++ = $(BUILDDIR)/src/cpp/libxmlrpc_server_abyss++.a
+
+CASPRINTF                = $(BUILDDIR)/lib/util/casprintf.o
+
+UTILS = $(CASPRINTF)
+
+
+# LIBXMLRPC_XML is the list of Xmlrpc-c libraries we need to parse
+# XML.  If we're using an external library to parse XML, this is null.
+# LDLIBS_XMLRPC_XML is the corresonding -l options.
+
+ifneq ($(ENABLE_LIBXML2_BACKEND),yes)
+  # We're using the internal Expat XML parser
+  LIBXMLRPC_XML = $(LIBXMLRPC_XMLPARSE) $(LIBXMLRPC_XMLTOK)
+  LDLIBS_XML = \
+        -L$(BUILDDIR)/lib/expat/xmlparse/.libs \
+       -lxmlrpc_xmlparse \
+        -L$(BUILDDIR)/lib/expat/xmltok/.libs \
+       -lxmlrpc_xmltok
+else
+  LDLIBS_XML = $(shell xml2-config --libs)
+endif
+
+
+##############################################################################
+#                           BUILD RULES                                      #
+##############################################################################
+
+# We use the srcdir and blddir symbolic links simply to make the make
+# rules easier to read in the make output.  We could use $(SRCDIR) and
+# $(BLDDIR) variables, but that makes the compile and link commands
+# a mile long.  Note that Make sometime figures that a directory which
+# is a dependency is newer than the symbolic link pointing to it and wants
+# to rebuild the symbolic link.  So we don't make $(BLDDIR) a
+# dependency of 'blddir'.
+
+blddir:
+       $(LN_S) $(BLDDIR) $@
+
+srcdir:
+       $(LN_S) $(SRCDIR) $@
+
+$(SUBDIRS:%=%/all): %/all: $(CURDIR)/%
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+           $(notdir $@) 
+
+$(SUBDIRS:%=%/install): %/install: $(CURDIR)/%
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+           $(notdir $@) 
+
+$(SUBDIRS:%=%/clean): %/clean: $(CURDIR)/%
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+           $(notdir $@) 
+
+$(SUBDIRS:%=%/distclean): %/distclean: $(CURDIR)/%
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+           $(notdir $@) 
+
+$(SUBDIRS:%=%/check): %/check: $(CURDIR)/%
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+           $(notdir $@) 
+
+$(SUBDIRS:%=%/distdir): %/distdir: $(CURDIR)/%
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+           $(notdir $@) 
+
+$(SUBDIRS:%=%/dep): %/dep: $(CURDIR)/%
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/$(SUBDIR)/$(dir $@)Makefile \
+           $(notdir $@) 
+
+$(BUILDDIR)/lib/wininet_transport/xmlrpc_wininet_transport.lo: FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/wininet_transport/Makefile \
+           $(notdir $@)
+
+$(BUILDDIR)/lib/curl_transport/xmlrpc_curl_transport.lo: FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/curl_transport/Makefile \
+           $(notdir $@)
+
+$(BUILDDIR)/lib/libwww_transport/xmlrpc_libwww_transport.lo: FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/libwww_transport/Makefile \
+           $(notdir $@)
+
+$(LIBXMLRPC_ABYSS): FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/abyss/src/Makefile \
+           $(notdir $@)
+
+$(LIBXMLRPC_XMLPARSE): FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/expat/xmlparse/Makefile \
+           $(notdir $@)
+
+$(LIBXMLRPC_XMLTOK): FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/expat/xmltok/Makefile \
+           $(notdir $@)
+
+$(LIBXMLRPC_UTIL): FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/libutil/Makefile \
+           $(notdir $@)
+
+$(LIBXMLRPC) $(LIBXMLRPC_CLIENT) $(LIBXMLRPC_SERVER): FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/src/Makefile \
+           $(notdir $@)
+
+$(LIBXMLRPC++) $(LIBXMLRPC_CLIENT++) $(LIBXMLRPC_SERVER++) \
+  $(LIBXMLRPC_SERVER_ABYSS++): FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/src/cpp/Makefile \
+           $(notdir $@)
+
+$(LIBXMLRPC_UTIL_A): $(LIBXMLRPC_UTIL)
+$(LIBXMLRPC_A): $(LIBXMLRPC)
+$(LIBXMLRPC_CLIENT_A): $(LIBXMLRPC_CLIENT)
+$(LIBXMLRPC_SERVER_ABYSS_A): $(LIBXMLRPC_SERVER_ABYSS)
+$(LIBXMLRPC_CGI_A): $(LIBXMLRPC_CGI)
+$(LIBXMLRPC_ABYSS_A): $(LIBXMLRPC_ABYSS)
+$(LIBXMLRPC_XMLPARSE_A): $(LIBXMLRPC_XMLPARSE)
+$(LIBXMLRPC_XMLTOK_A): $(LIBXMLRPC_XMLTOK)
+
+$(UTILS): FORCE
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/lib/util/Makefile \
+           $(notdir $@)
+
+# About version.h:  This is a built header file, which means it is a supreme
+# pain in the ass.  The biggest problem is that when we automatically make
+# dependencies (Makefile.depend), it doesn't exist yet.  This means Gcc
+# generates a dependency on it being in the local directory.  Therefore,
+# we generate it in the local directory, as a symbolic link, wherever it
+# is needed.  But the original is always in the top level directory,
+# generated by a rule in that directory's make file.  Problem 2 is that
+# the top directory's make file includes Makefile.common, so the rules
+# below conflict with it.  That's what OMIT_VERSION_H is for.
+
+ifneq ($(OMIT_VERSION_H),Y)
+
+$(BUILDDIR)/version.h:
+       $(MAKE) -C $(dir $@) -f $(SRCDIR)/GNUmakefile $(notdir $@)
+
+version.h: $(BUILDDIR)/version.h
+       $(LN_S) $< $@
+
+endif
+
+$(BUILDDIR)/include/xmlrpc-c/config.h:
+       $(MAKE) -C $(BUILDDIR)/include -f $(SRCDIR)/include/Makefile \
+          xmlrpc-c/config.h
+
+ifneq ($(OMIT_TRANSPORT_CONFIG_H),Y)
+$(BUILDDIR)/transport_config.h:
+       $(MAKE) -C $(dir $@) $(notdir $@)
+endif
+
+$(ALL_OBJS): $(BUILDDIR)/include/xmlrpc-c/config.h
+
+
+##############################################################################
+#                          SHARED LIBRARY RULES                              #
+##############################################################################
+
+ifeq ($(SHARED_LIB_TYPE),unix)
+  include $(SRCDIR)/unix-common.make
+  endif
+
+ifeq ($(SHARED_LIB_TYPE),irix)
+  include $(SRCDIR)/irix-common.make
+  endif
+
+ifeq ($(SHARED_LIB_TYPE),dll)
+  include $(SRCDIR)/dll-common.make
+  endif
+
+ifeq ($(SHARED_LIB_TYPE),dylib)
+  include $(SRCDIR)/dylib-common.make
+  endif
+
+ifeq ($(SHARED_LIB_TYPE),NONE)
+  install-shared-libraries:
+  endif
+
+
+##############################################################################
+#                           INSTALL RULES                                    #
+#                      (except shared libraries)                             #
+##############################################################################
+
+MKINSTALLDIRS = $(SHELL) $(SRCDIR)/mkinstalldirs
+
+.PHONY: install-common install-libraries install-headers install-bin
+install-common: \
+  install-ltlibraries install-static-libraries install-shared-libraries \
+  install-headers install-bin
+
+INSTALL_LIB_CMD = $(INSTALL_DATA) $$p $(DESTDIR)$(LIBINST_DIR)/$$p
+RANLIB_CMD = $(RANLIB) $(DESTDIR)$(LIBINST_DIR)/$$p
+
+install-static-libraries: $(STATIC_LIBRARIES_TO_INSTALL)
+       $(MKINSTALLDIRS) $(DESTDIR)$(LIBINST_DIR)
+       @list='$(STATIC_LIBRARIES_TO_INSTALL)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(INSTALL_LIB_CMD)"; \
+           $(INSTALL_LIB_CMD); \
+         else :; fi; \
+       done
+       @$(POST_INSTALL)
+       @list='$(STATIC_LIBRARIES_TO_INSTALL)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(RANLIB_CMD)"; \
+           $(RANLIB_CMD); \
+         else :; fi; \
+       done
+
+LIBTOOL_INSTALL_CMD = $(LIBTOOL) --mode=install \
+  $(INSTALL_SHLIB) $$p $(DESTDIR)$(LIBINST_DIR)/$$p
+
+install-ltlibraries: $(LTLIBRARIES_TO_INSTALL)
+       $(MKINSTALLDIRS) $(DESTDIR)$(LIBINST_DIR)
+       @list='$(LTLIBRARIES_TO_INSTALL)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(LIBTOOL_INSTALL_CMD)"; \
+           $(LIBTOOL_INSTALL_CMD); \
+         else :; fi; \
+       done
+
+HEADERDESTDIR = $(DESTDIR)$(HEADERINST_DIR)
+INSTALL_HDR_CMD = $(INSTALL_DATA) $$d$$p $(HEADERDESTDIR)/$$p 
+
+install-headers: $(HEADERS_TO_INSTALL)
+       $(MKINSTALLDIRS) $(HEADERDESTDIR)
+       $(MKINSTALLDIRS) $(HEADERDESTDIR)/xmlrpc-c
+       @list='$(HEADERS_TO_INSTALL)'; for p in $$list; do \
+         if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
+         echo " $(INSTALL_HDR_CMD)"; \
+         $(INSTALL_HDR_CMD); \
+       done
+
+
+INSTALL_PROGRAM_CMD = $(INSTALL_PROGRAM) $$p $(DESTDIR)$(PROGRAMINST_DIR)/$$p
+
+install-bin: $(PROGRAMS_TO_INSTALL) $(DESTDIR)$(PROGRAMINST_DIR)
+       @list='$(PROGRAMS_TO_INSTALL)'; \
+         for p in $$list; do \
+          echo "$(INSTALL_PROGRAM_CMD)"; \
+          $(INSTALL_PROGRAM_CMD); \
+          done
+
+$(DESTDIR)$(PROGRAMINST_DIR):
+       $(MKINSTALLDIRS) $@
+
+
+##############################################################################
+#                           MISCELLANEOUS RULES                              #
+##############################################################################
+
+.PHONY: clean-common
+clean-common:
+       rm -f *.o *.a *.s *.i *.la *.lo
+       rm -f *.$(SHLIB_SUFFIX) *.$(SHLIB_SUFFIX).*
+       rm -rf .libs
+
+.PHONY: distclean-common
+distclean-common:
+# Makefile.depend is generated by 'make dep' and contains only dependencies
+# that make parts get _rebuilt_ when parts upon which they depend change.
+# It does not contain dependencies that are necessary to cause a part to
+# get built in the first place.  E.g. if foo.c uses bar.h and bar.h gets built
+# by a make rule, you must put the dependency of foo.c on bar.h somewhere
+# besides Makefile.depend.
+#
+# Because of this, a user doesn't need Makefile.depend, because he
+# doesn't modify source files.  A developer, on the other hand, must make his
+# own Makefile.depend, because 'make dep' creates Makefile.depend with 
+# absolute pathnames, specific to the developer's system.
+#
+# So we empty out Makefile.depend here.  The developer must do 'make dep' if
+# he wants to edit and rebuild.
+#
+# Other projects have 'make distclean' _remove_ Makefile.depend and then
+# have 'make' automatically build Makefile.depend.  We have
+# found that to be an utter disaster -- it's way too complicated and prone
+# to failure, especially with built .h files.  Better not to burden the user,
+# who gains nothing from it, with that.
+#
+       cat /dev/null >Makefile.depend
+       rm -f TAGS
+       rm -f blddir srcdir
+ifneq ($(OMIT_VERSION_H),Y)
+       rm -f version.h
+endif
+
+.PHONY: distdir-common
+distdir-common:
+       @for file in $(DISTFILES); do \
+         d=$(SRCDIR); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(DISTDIR)/$$file; \
+         else \
+           test -f $(DISTDIR)/$$file \
+           || ln $$d/$$file $(DISTDIR)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(DISTDIR)/$$file || :; \
+         fi; \
+       done
+
+TAGS: $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+   if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+   fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+DEP_SOURCES = $(wildcard *.c *.cpp)
+
+# This is a filter to turn "foo.o:" rules into "foo.o foo.lo:" because Libtool
+# uses .lo for object files.  I'd like to purge the build of Libtool some day
+# and eliminate this complication.
+
+LIBTOOL_DEPEND_MASSAGER = perl -walnpe's{^(.*)\.o:}{$$1.o $$1.lo:}'
+
+
+
+.PHONY: dep-common
+dep-common: FORCE
+ifneq ($(DEP_SOURCES)x,x)
+       -$(CC) -MM -MG -I. $(INCLUDES) $(DEP_SOURCES) | \
+         $(LIBTOOL_DEPEND_MASSAGER) \
+         >Makefile.depend
+endif
+
+Makefile.depend:
+       cat /dev/null >$@
+
+# The automatic dependency generation is a pain in the butt and
+# totally unnecessary for people just installing the distributed code,
+# so to avoid needless failures in the field and a complex build, the
+# 'distclean' target simply makes Makefile.depend an empty file.  A
+# developer may do 'make dep' to create a Makefile.depend full of real
+# dependencies.
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+
+# Use the FORCE target as a dependency to force a target to get remade
+FORCE:
diff --git a/Makefile.config.in b/Makefile.config.in
new file mode 100644 (file)
index 0000000..07f37af
--- /dev/null
@@ -0,0 +1,253 @@
+# Makefile.config is generated by 'configure' using Makefile.config.in
+# as a template and information that 'configure' gathers from the build
+# system and from user options.
+
+# Makefile.config should someday replace most of the other files that
+# 'configure' generates, thus simplifying development and customization.
+# Makefile.config is intended to contain information specific to the
+# particular build environment or user build choices.
+
+# Furthermore, most of the logic in 'configure', and thus 'configure.in',
+# should go into the make files to simplify the build.  Makefile.config
+# should just pass raw configure variables through to the make file.
+
+# Tokens of the form @TOKEN@ in the template file get replaced by
+# 'configure' with the values of variables of the same name within
+# 'configure', because of a AC_SUBST(TOKEN) statement in the
+# 'configure.in' from which 'configure' was built.
+
+# Here are the options the user chose on 'configure':
+
+ENABLE_ABYSS_SERVER    = @ENABLE_ABYSS_SERVER@
+ENABLE_ABYSS_THREADS   = @ENABLE_ABYSS_THREADS@
+ENABLE_CPLUSPLUS       = @ENABLE_CPLUSPLUS@
+ENABLE_CGI_SERVER      = @ENABLE_CGI_SERVER@
+ENABLE_LIBXML2_BACKEND = @ENABLE_LIBXML2_BACKEND@
+
+MUST_BUILD_WININET_CLIENT = @MUST_BUILD_WININET_CLIENT@
+MUST_BUILD_CURL_CLIENT    = @MUST_BUILD_CURL_CLIENT@
+MUST_BUILD_LIBWWW_CLIENT  = @MUST_BUILD_LIBWWW_CLIENT@
+
+HAVE_WCHAR_H_DEFINE = @HAVE_WCHAR_H_DEFINE@
+
+# Stuff 'configure' figured out about our build platform:
+
+SHELL = @SHELL@
+CC = @CC@
+CXX = @CXX@
+CCLD = $(CC)
+CXXLD = $(CXX)
+AR = ar
+RANLIB = @RANLIB@
+LN_S = @LN_S@
+INSTALL = $(SRCDIR)/install-sh
+
+C_COMPILER_GNU = @C_COMPILER_GNU@
+CXX_COMPILER_GNU = @CXX_COMPILER_GNU@
+
+# Stuff 'configure' figured out via AC_CANONICAL_HOST macro in configure.in
+# and config.guess program and 'configure' command options:
+
+# HOST_OS names the operating system on which Xmlrpc-c is to run.
+# E.g. "linux-gnu".
+HOST_OS = @host_os@
+
+# Hardcoded in configure.in:
+XMLRPC_C_VERSION = @VERSION@
+
+###############################################################################
+
+MUST_BUILD_CLIENT = no
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+  MUST_BUILD_CLIENT = yes
+endif
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+  MUST_BUILD_CLIENT = yes
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+  MUST_BUILD_CLIENT = yes
+endif
+
+
+##############################################################################
+# SHARED LIBRARY STUFF
+##############################################################################
+
+# Shared libraries are very difficult, because how you build and use
+# them varies greatly from one platform to the next.  # There are two
+# ways shared libraries get built in the Xmlrpc-c build: Libtool and
+# direct.  In the beginning, there was just Libtool.  Libtool is
+# supposed to solve the problem of the diversity of shared libraries,
+# but it does it by adding a layer of complexity and yet another build
+# tool a developer has to know.  The encapsulation of shared library
+# building reduced flexibility and makes diagnosing problems much
+# harder.  So we are phasing out Libtool.  New libraries (in
+# particular, the C++ ones) don't involve Libtool.  Some day, the
+# older ones won't either, but we aren't as good yet with the direct
+# method as with Libtool, and we don't want to break something that's
+# working.
+
+# First, we break down shared library schemes into a few major types,
+# and indicate the type by SHARED_LIB_TYPE.
+
+# We also have a bunch of other make variables that reflect the different
+# ways we have to build on and for different platforms:
+
+# CFLAGS_SHLIB is a set of flags needed to compile a module which will
+# become part of a shared library.
+
+# On older systems, you have to make shared libraries out of position
+# independent code, so you need -fpic or -fPIC here.  (The rule is: if
+# -fpic works, use it.  If it bombs, go to -fPIC).  On newer systems,
+# it isn't necessary, but can save real memory at the expense of
+# execution speed.  Without position independent code, the library
+# loader may have to patch addresses into the executable text.  On an
+# older system, this would cause a program crash because the loader
+# would be writing into read-only shared memory.  But on newer
+# systems, the system silently creates a private mapping of the page
+# or segment being modified (the "copy on write" phenomenon).  So it
+# needs its own private real page frame.
+
+# We have seen -fPIC required on IA64 and AMD64 machines (GNU
+# compiler/linker).  Build-time linking fails without it.  I don't
+# know why -- history seems to be repeating itself.  2005.02.23.
+
+# SHLIB_CLIB is the link option to include the C library in a shared library,
+# normally "-lc".  On typical systems, this serves no purpose.  On some,
+# though, it causes information about which C library to use to be recorded
+# in the shared library and thus choose the correct library among several or
+# avoid using an incompatible one.  But on some systems, the link fails.
+# On 2002.09.30, "John H. DuBois III" <spcecdt@armory.com> reports that on 
+# SCO OpenServer, he gets the following error message with -lc:
+#
+#  -lc; relocations referenced  ;  from file(s) /usr/ccs/lib/libc.so(random.o);
+#   fatal error: relocations remain against allocatable but non-writable 
+#   section: ; .text
+#
+# On Bryan's system, with gcc 2.95.3 and glibc 2.2.2, -lc causes
+# throws (from anywhere in a program that links the shared library)
+# not to work.  I have no idea how.
+
+# LDFLAGS_SHLIB is the linker (Ld) flags needed to generate a shared
+# library from object files.  It may use $(SONAME) as the soname for
+# the shared library being created (assuming sonames exist).
+
+# We build shared libraries only for platforms for which we've figured
+# out how.  For the rest, we have this default:
+SHARED_LIB_TYPE = NONE
+
+ifeq ($(HOST_OS),linux-gnu)
+  # Assume linker is GNU Compiler (gcc)
+  SHARED_LIB_TYPE = unix
+  SHLIB_SUFFIX = so
+#  SHLIB_CLIB = -lc
+  LDFLAGS_SHLIB = -shared -Wl,-soname,$(SONAME) $(SHLIB_CLIB)
+endif
+
+ifeq ($(findstring solaris,$(HOST_OS)),solaris)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = unix
+  SHLIB_SUFFIX = so
+  # Solaris compiler can't take multiple ld options as -Wl,-a,-b .  Ld sees
+  # -a,-b in that case.
+  LDFLAGS_SHLIB = -Wl,-Bdynamic -Wl,-G -Wl,-h -Wl,$(SONAME)
+  CFLAGS_SHLIB = -Kpic
+endif
+
+ifeq ($(HOST_OS),aix)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = unix
+  SHLIB_SUFFIX = a
+  LDFLAGS_SHLIB = -qmkshrobj
+endif
+
+ifeq ($(HOST_OS),irix)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = irix
+  SHLIB_SUFFIX = so
+  LDFLAGS_SHLIB = -shared -n32
+endif
+
+ifeq ($(HOST_OS),hpux)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = unix
+  SHLIB_SUFFIX = sl
+  LDFLAGS_SHLIB: -shared -fPIC
+endif
+
+ifeq ($(HOST_OS),osf)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = unix
+  SHLIB_SUFFIX = so
+  LDFLAGS_SHLIB = -shared -expect_unresolved
+endif
+
+ifeq ($(findstring netbsd,$(HOST_OS)),netbsd)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = unix
+  SHLIB_SUFFIX = so
+  CFLAGS_SHLIB = -fpic
+endif
+
+ifeq ($(HOST_OS),darwin)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = dylib
+  SHLIB_SUFFIX = dylib
+endif
+
+ifeq ($(HOST_OS),beos)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = unix
+  SHLIB_SUFFIX = so
+  LDFLAGS_SHLIB = -nostart
+endif
+
+ifeq ($(HOST_OS),cygwin)
+  # This code is not finished; that's why we don't set SHARED_LIB_TYPE.
+  # If you can finish it and make it work on AIX, please do.
+  # SHARED_LIB_TYPE = dll
+  SHLIB_SUFFIX = dll
+endif
+
+##############################################################################
+#                     MISCELLANEOUS
+##############################################################################
+
+# BUILDTOOL_CC is the compiler to use to generate build tools, which we
+# will then run to build product.  The typical reason this would be
+# different from CC is that you're cross-compiling: the product will run
+# in Environment A, but you're building in Environment B, so you must
+# build the build toos for Environment B.
+
+# The cross compiling user can update Makefile.config or override
+# BUILDTOOL_CC on a make command.
+
+BUILDTOOL_CC = $(CC)
+BUILDTOOL_CCLD = $(CCLD)
+
+# Here are the commands 'make install' uses to install various kinds of files:
+
+INSTALL_PROGRAM = $(INSTALL) -c -m 755
+INSTALL_SHLIB = $(INSTALL) -c -m 755
+INSTALL_DATA = $(INSTALL) -c -m 644
+INSTALL_SCRIPT = $(INSTALL) -c -m 755
+
+# Here are the locations at which 'make install' puts files:
+
+# DESTDIR is designed to be overriden at make time in order to relocate
+# the entire install into a subdirectory.
+DESTDIR =
+
+exec_prefix = @exec_prefix@
+prefix = @prefix@
+LIBINST_DIR = @libdir@
+HEADERINST_DIR = @includedir@
+PROGRAMINST_DIR = @bindir@
diff --git a/Makefile.depend b/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..eefe8e1
--- /dev/null
+++ b/README
@@ -0,0 +1,55 @@
+This is the source code for XML-RPC for C/C++, called Xmlrpc-c for short.
+
+XML-RPC for C/C++ is programming libraries and related tools to help you
+write an XML-RPC server or client in C or C++.
+
+Documentation for the package is at
+
+  http://xmlrpc-c.sourceforge.net/doc
+
+See the Xmlrpc-c website at:
+
+  http://xmlrpc-c.sourceforge.net/
+
+
+PREREQUISITES
+-------------
+
+To build a useful Xmlrpc-c client library, you'll need to have at
+least one HTTP library.  Xmlrpc-c knows how to use W3C Libwww (Version
+5.3.2 or newer), Curl, and Wininet.  The configurator gives you the
+option of building libraries that use any or all of these, and
+defaults to every one you appear to have installed.  If you don't
+appear to have any installed, the configurator causes the build to
+omit client facilities altogether.
+
+Information about W3C Libwww, including how to get it are at
+<http://www.w3.org/Library>.
+
+For Curl, see <http://curl.haxx.se>.
+
+Wininet comes with Windows, and isn't available for any other platform.
+
+You also need an XML parser/builder library.  An old version of Expat
+is included in the package and used by default, so there's no actual
+prerequisite here.  But if you separately obtain Libxml2, you can
+configure the build to use that instead.  There's no really pressing
+reason to do that, though.
+
+BUILDING, INSTALLING
+--------------------
+
+See the file doc/INSTALL.
+
+In the simplest case, it's just a conventional
+
+  $ ./configure
+  $ make
+  $ make install
+
+
+ADDITIONAL INFORMATION
+----------------------
+
+See the doc/ directory of the source tree for information about the
+source code.  User documentation is on the web, as described above.
diff --git a/Windows/.cvsignore b/Windows/.cvsignore
new file mode 100644 (file)
index 0000000..cc8f7bb
--- /dev/null
@@ -0,0 +1,9 @@
+Debug\r
+Release\r
+*.log\r
+*.ncb\r
+*.opt\r
+*.plg\r
+*.suo\r
+BuildLog.htm\r
+\r
diff --git a/Windows/ConfigureWin32.bat b/Windows/ConfigureWin32.bat
new file mode 100644 (file)
index 0000000..75d8421
--- /dev/null
@@ -0,0 +1,7 @@
+@echo off\r
+echo creating Win32 header files...\r
+copy .\xmlrpc_win32_config.h ..\config.h\r
+copy .\xmlrpc_win32_config.h ..\xmlrpc_config.h\r
+copy .\transport_config_win32.h ..\transport_config.h\r
+echo completed creating win32 header files.\r
+pause\r
diff --git a/Windows/ReadMeWin32.txt b/Windows/ReadMeWin32.txt
new file mode 100644 (file)
index 0000000..48fa1d3
--- /dev/null
@@ -0,0 +1,116 @@
+Build Instructions For XML-RPC For C/C++ On Windows
+---------------------------------------------------
+
+The following instructions do not fully work in this release.  There
+is no trivial way to build this release for Windows.  The last release
+that was known to build without special effort on the part of the user
+is 1.02.
+
+Since then, nobody has maintained the code for Windows, and changes that
+were made for other platforms broke some things for Windows.  Most likely,
+anyone with a passing knowledge of building C code on Windows could
+update this code to work on Windows without any in-depth study of it.  If
+you do so, please contribute your work to save other users the trouble.
+
+The majority of the work that needs to be done to make the code build on
+Windows is simply adjusting project files to reflect the fact that files
+have been created, deleted, and moved since they were written.
+
+
+This release includes the option to compile an "http.sys" version of an
+XML-RPC server.  If you do not wish to build in the http.sys server,
+set the MUST_BUILD_HTTP_SYS_SERVER to 0 in the transport_config_win32.h and/or
+the transport_config.h file.  Successful conpilation requires installation 
+of the Microsoft Platform SDK for Windows XP SP2 (or later) to get the latest 
+header and link libraries required to support this functionality.  After 
+installation, be sure to properly register the directories as documented 
+in the Platform SDK help file topic "Installing the Platform SDK with 
+Visual Studio".  Download the Platform SDK from:
+http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+
+To create the three headers required for Win32 WinInet compilation, run the
+ConfigureWin32.bat found in the Windows directory.  If you wish to alter the
+transports that are built to include curl or libwww, adjust the preprocessor
+definitions at the top of the transport_config_win32.h and/or
+the transport_config.h files.  See the file UsingCURLinWin32.txt for
+more information on using the curl transport.  
+
+To compile, open the xmlrpc.dsw file in Visual Studio 6 or greater.  The 
+project will convert and work fine in Visual Studio 2003 as well - 
+other versions of Visual Studio were not tested.
+NOTE: If you get an error while opening or converting the project files,
+it is likely due to using WinRar or similar to decompress the distribution
+tarball.  You can use WinZip or another utility to correctly decompress the
+.tgz file.
+
+Suggested testing for evaluation of the library involves a few projects.  
+Here is a quick getting started guide:
+
+1) Set the Active Project to query_meerkat and build it in release or debug 
+   modes.  The dependent projects will be built automatically.  In the 
+   project settings dialog, add the argument for what you wish to query 
+   meerkat for - "Windows" is a good query.  Run the project.  This will 
+   query the meerkat server for articles related to windows and output the 
+   results to the console.
+
+2) Set the Active Project to xmlrpc_sample_add_server and build it in 
+   release or debug modes.  The dependent projects will be built 
+   automatically.  In the project settings dialog, add the argument for 
+   the port to 8080.  This will run the server sample which adds two 
+   numbers and returns a result.  You should run this from a command 
+   prompt instead of through Visual Studio so you may run the sample
+   client as well.
+
+3) Set the Active Project to xmlrpc_sample_add_sync_client or 
+   xmlrpc_sample_add_async_client and build it in release or debug modes.  
+   The dependent projects will be built automatically.  This will run 
+   the client sample which submits two numbers to be added to the server 
+   application as described above and displays the result.  Note that the 
+   client example comes in the sync and async varieties.
+
+Steven Bone
+July 27, 2005
+sbone@pobox.com
+
+WIN32 CHANGES
+
+Changes from the 1.02 release for Win32:
+1) Option to easily disable the http.sys server for those who do not need
+   it or wish to download the Platform SDK.
+
+Changes from the 1.01 -> 1.02 release for Win32:
+1) Project files for gennmtab, xmlparse, and xmltok updated to include the 
+   path to the xmlrpc_config.h file.
+2) Bugfix for WinInet authentication.
+3) Supports xmlrpc_xportparms, xmlrpc_wininet_xportparms added
+   *potential breaking change* - now by default we fail on invalid
+   SSL certs, use the xmlrpc_wininet_xportparms option to enable old
+   behavior.
+4) Added project file for xmlrpc_sample_auth_client
+5) Added project and src for a http.sys based xmlrpc-c server.  See comments
+   in the source files.  This supports Windows XP SP2 and Windows Server
+   2003 and allows other http.sys based applications to bind to the same
+   port.  In Server 2003, IIS uses http.sys and thus the XML-RPC server
+   can be run on the standard port 80 along with IIS.  The sample also
+   supports https and basic authentication.  It tested OK with
+   http://validator.xmlrpc.com/  Note that the Platform SDK headers and
+   link libraries for Windows XP SP2 or newer are required to compile
+   xmlrpc-c for this module.  If you are not using this server, it is 
+   safe to exclude the xmlrpc_server_w32httpsys.c file from the xmlrpc
+   project and these dependencies will not be required.  You can get the 
+   latest platform SDK at 
+   http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+   Be sure after installation to choose the program to "register the PSDK
+   directories with Visual Studio" so the newer headers are found.
+6) Better support for libcurl.  Updated project files, transport_config_win32.h,
+   added documentation UsingCURLinWin32.txt.
+   
+Changes from the 1.00 -> 1.01 release for Win32:
+1) Project files now reflect static linking for the expat XML library.
+2) Example projects were created/updated to keep them in sync with the 
+   distribution.  The project files were moved into the .\Windows 
+   directory
+3) Projects for the rpc and cpp tests were created.  The 
+   xmlrpc_win32_config.h defines the directory for the test files relative 
+   to the output directory
+4) Major refactoring of the Wininet Transport.   
\ No newline at end of file
diff --git a/Windows/UsingCURLinWin32.txt b/Windows/UsingCURLinWin32.txt
new file mode 100644 (file)
index 0000000..fe8b934
--- /dev/null
@@ -0,0 +1,64 @@
+Background:
+Let\92s say you need to support a xmlrpc-c client running as a service.  In this
+situation you cannot use WinInet.  Details of the restriction can be found on
+the libcurl website or various Microsoft KB articles.  The alternative is to use
+libcurl.  This document describes the steps required to use libcurl as your
+transport mechanism as supported by the latest files and projects provided in
+the xmlrpc-c distribution.  The assumption is that you can successfully compile
+the distribution of xmlrpc-c.
+
+Overview:
+The default projects in xmlrpc-c create standalone executables that do not
+require other DLL\92s (release mode).  While the case can be made for this
+behavior pro and con, it is beyond this document to justify it.  Therefore, we
+need to create static link libraries for libcurl that mimics this behavior. 
+Once the link libraries are created, we can then add them (plus the requisite
+curl headers) into the xmlrpc-c project.  Finally, we enable the compilation of
+the curl transport file and tell xmlrpc-c that we will be using curl.  Lastly,
+we build and test the project.
+
+Steps to use CURL with Win32 xmlrpc-c:
+1. Download the CURL source.  In the \93include\94 folder of the CURL distribution,
+copy the curl directory to the \93lib\94 directory of xmlbpc-c.  When you are done
+with this step, you should have a curl.h file located in the directory
+xmlrpc-c\lib\curl\.  The xmlrpc project looks in this relative path for the
+necessary headers.
+
+2. In the CURL distribution, lib directory, is a file called Makefile.vc6.  Edit
+this file.  The line starting with CCNODBG should be changed to:
+CCNODBG    = cl.exe /MT /O2 /DNDEBUG
+The /MT option links with the Multithreaded non-dll version of the c runtime. 
+If this change is not made, the project will not link, as this is the default
+setting for the xmlrpc-c projects.  In debug mode, we use the dll version of the
+c runtime as it makes memory leak checking tools work better.
+
+3. Open a command prompt window and run the vcvars32.bat file in your Visual C++
+distribution.  If you are using Studio 2002 or 2003, use the \93Visual Studio
+Command Prompt\94 from the Start menu to open the console.
+
+4. Compile release and debug mode libraries.  For the purposes of this tutorial,
+we are going to build only the curl library without ssl or zlib support.  In the
+command prompt, navigate to the curl\lib directory and execute the following
+commands:
+nmake -f Makefile.vc6 CFG=debug
+nmake -f Makefile.vc6 CFG=release
+
+5. The above step should have generated two static link libraries in the
+curl\lib directory: libcurl.lib and libcurld.lib.  Copy these files into the
+root of the xmlrpc-c\lib\ directory.  This step ends our involvement with the
+actual CURL distribution.  The remainder of the steps are for XMLRPC-C.
+
+6. Open the xmlrpc-c Visual Studio workspace (Instructions for VC++ 6, other
+versions are slightly different).  In File View, expand the xmlrpc project. 
+Under \93Source Files\94 there is an entry for xmlrpc_curl_transport.c  This is not
+included in any build paths by default.  To enable it for compilation, right
+click the file to change the settings.  In the dropdown, select \93All
+Configurations.\94  Pick the General tab and uncheck the \93Exclude File From Build\94
+setting.  Press OK to save your changes to the project.
+
+7.  In the \93Header Files\94 section of the xmlrpc project is a file called
+\93transport_config.h\94.  Edit this file to set the MUST_BUILD_CURL_CLIENT to 1,
+and if you wish to change the default transport to curl, change the
+XMLRPC_DEFAULT_TRANSPORT to \93curl\94
+
+8. Compile and test one or more of the sample client projects.
diff --git a/Windows/abyss.dsp b/Windows/abyss.dsp
new file mode 100644 (file)
index 0000000..8b19d8a
--- /dev/null
@@ -0,0 +1,140 @@
+# Microsoft Developer Studio Project File - Name="abyss" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Static Library" 0x0104\r
+\r
+CFG=abyss - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "abyss.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "abyss.mak" CFG="abyss - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "abyss - Win32 Release" (based on "Win32 (x86) Static Library")\r
+!MESSAGE "abyss - Win32 Debug" (based on "Win32 (x86) Static Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "abyss - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release\Abyss"\r
+# PROP Intermediate_Dir "Release\Abyss"\r
+# PROP Target_Dir ""\r
+MTL=midl.exe\r
+LINK32=link.exe -lib\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /I "..\lib\util\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo /out:"..\lib\abyss.lib"\r
+\r
+!ELSEIF  "$(CFG)" == "abyss - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug\abyss"\r
+# PROP Intermediate_Dir "Debug\abyss"\r
+# PROP Target_Dir ""\r
+MTL=midl.exe\r
+LINK32=link.exe -lib\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\include" /I "..\lib\util\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo /out:"..\lib\abyssD.lib"\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "abyss - Win32 Release"\r
+# Name "abyss - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\conf.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\conn.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\data.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\file.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\http.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\server.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\socket.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\thread.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\token.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\trace.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=..\lib\abyss\src\token.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/Windows/all.dsp b/Windows/all.dsp
new file mode 100644 (file)
index 0000000..c3f9955
--- /dev/null
@@ -0,0 +1,97 @@
+# Microsoft Developer Studio Project File - Name="all" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) External Target" 0x0106\r
+\r
+CFG=all - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "all.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "all.mak" CFG="all - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "all - Win32 Release" (based on "Win32 (x86) External Target")\r
+!MESSAGE "all - Win32 Debug" (based on "Win32 (x86) External Target")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+\r
+!IF  "$(CFG)" == "all - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Cmd_Line ""\r
+# PROP BASE Rebuild_Opt ""\r
+# PROP BASE Target_File "../config.h"\r
+# PROP BASE Bsc_Name ""\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Cmd_Line ""\r
+# PROP Rebuild_Opt ""\r
+# PROP Target_File "../all"\r
+# PROP Bsc_Name ""\r
+# PROP Target_Dir ""\r
+\r
+!ELSEIF  "$(CFG)" == "all - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Cmd_Line ""\r
+# PROP BASE Rebuild_Opt ""\r
+# PROP BASE Target_File "../config.h"\r
+# PROP BASE Bsc_Name ""\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir ""\r
+# PROP Intermediate_Dir ""\r
+# PROP Cmd_Line ""\r
+# PROP Rebuild_Opt ""\r
+# PROP Target_File "../all"\r
+# PROP Bsc_Name ""\r
+# PROP Target_Dir ""\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "all - Win32 Release"\r
+# Name "all - Win32 Debug"\r
+\r
+!IF  "$(CFG)" == "all - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "all - Win32 Debug"\r
+\r
+!ENDIF \r
+\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/Windows/all.vcproj b/Windows/all.vcproj
new file mode 100644 (file)
index 0000000..b3e1baa
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="all"\r
+       SccProjectName=""\r
+       SccLocalPath=""\r
+       Keyword="MakeFileProj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug"\r
+                       IntermediateDirectory=".\Debug"\r
+                       ConfigurationType="10"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release"\r
+                       IntermediateDirectory=".\Release"\r
+                       ConfigurationType="10"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/configwin32.dsp b/Windows/configwin32.dsp
new file mode 100644 (file)
index 0000000..e806f15
--- /dev/null
@@ -0,0 +1,97 @@
+# Microsoft Developer Studio Project File - Name="configwin32" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) External Target" 0x0106\r
+\r
+CFG=configwin32 - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE\r
+!MESSAGE NMAKE /f "configwin32.mak".\r
+!MESSAGE\r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE\r
+!MESSAGE NMAKE /f "configwin32.mak" CFG="configwin32 - Win32 Debug"\r
+!MESSAGE\r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE\r
+!MESSAGE "configwin32 - Win32 Release" (based on "Win32 (x86) External Target")\r
+!MESSAGE "configwin32 - Win32 Debug" (based on "Win32 (x86) External Target")\r
+!MESSAGE\r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+\r
+!IF  "$(CFG)" == "configwin32 - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Cmd_Line "ConfigureWin32.bat"\r
+# PROP BASE Rebuild_Opt ""\r
+# PROP BASE Target_File "../config.h"\r
+# PROP BASE Bsc_Name ""\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Cmd_Line "ConfigureWin32.bat"\r
+# PROP Rebuild_Opt ""\r
+# PROP Target_File "../config.h"\r
+# PROP Bsc_Name ""\r
+# PROP Target_Dir ""\r
+\r
+!ELSEIF  "$(CFG)" == "configwin32 - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Cmd_Line "ConfigureWin32.bat"\r
+# PROP BASE Rebuild_Opt ""\r
+# PROP BASE Target_File "../config.h"\r
+# PROP BASE Bsc_Name ""\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir ""\r
+# PROP Intermediate_Dir ""\r
+# PROP Cmd_Line "ConfigureWin32.bat"\r
+# PROP Rebuild_Opt ""\r
+# PROP Target_File "../config.h"\r
+# PROP Bsc_Name ""\r
+# PROP Target_Dir ""\r
+\r
+!ENDIF\r
+\r
+# Begin Target\r
+\r
+# Name "configwin32 - Win32 Release"\r
+# Name "configwin32 - Win32 Debug"\r
+\r
+!IF  "$(CFG)" == "configwin32 - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "configwin32 - Win32 Debug"\r
+\r
+!ENDIF\r
+\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/Windows/configwin32.vcproj b/Windows/configwin32.vcproj
new file mode 100644 (file)
index 0000000..f7ce8b7
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="configwin32"\r
+       SccProjectName=""\r
+       SccLocalPath=""\r
+       Keyword="MakeFileProj">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".."\r
+                       IntermediateDirectory=".."\r
+                       ConfigurationType="10"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                               Description="Copy Windows config header files to project root"\r
+                               CommandLine="ConfigureWin32.bat"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".."\r
+                       IntermediateDirectory=".."\r
+                       ConfigurationType="10"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                               Description="Copy Windows config header files to project root"\r
+                               CommandLine="ConfigureWin32.bat"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/cpptest.dsp b/Windows/cpptest.dsp
new file mode 100644 (file)
index 0000000..babbc98
--- /dev/null
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="cpptest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=cpptest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "cpptest.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "cpptest.mak" CFG="cpptest - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "cpptest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "cpptest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "cpptest"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "cpptest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\cpptest"
+# PROP Intermediate_Dir "Release\cpptest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\src" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\lib\xmlrpc.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\cpptest.exe"
+
+!ELSEIF  "$(CFG)" == "cpptest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\cpptest"
+# PROP Intermediate_Dir "Debug\cpptest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\src" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\lib\xmlrpcD.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\cpptest.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "cpptest - Win32 Release"
+# Name "cpptest - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\src\cpptest.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Windows/cpptest.vcproj b/Windows/cpptest.vcproj
new file mode 100644 (file)
index 0000000..1d50717
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="cpptest"\r
+       SccProjectName="cpptest"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release\cpptest"\r
+                       IntermediateDirectory=".\Release\cpptest"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..,../src"\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="odbc32.lib odbccp32.lib ..\lib\xmlrpc.lib"\r
+                               OutputFile="../Bin/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Release\cpptest/cpptest.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\cpptest"\r
+                       IntermediateDirectory=".\Debug\cpptest"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..,../src"\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="odbc32.lib odbccp32.lib ..\lib\xmlrpcD.lib"\r
+                               OutputFile="../Bin/$(ProjectName)D.exe"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Debug\cpptest/cpptest.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath="..\src\cpptest.cpp">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/query_meerkat.dsp b/Windows/query_meerkat.dsp
new file mode 100644 (file)
index 0000000..2ffb15b
--- /dev/null
@@ -0,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="query_meerkat" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=query_meerkat - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "query_meerkat.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "query_meerkat.mak" CFG="query_meerkat - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "query_meerkat - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "query_meerkat - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "query_meerkat"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "query_meerkat - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\query_meerkat"
+# PROP Intermediate_Dir "Release\query_meerkat"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WinInet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\query_meerkat.exe"
+
+!ELSEIF  "$(CFG)" == "query_meerkat - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\query_meerkat"
+# PROP Intermediate_Dir "Debug\query_meerkat"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\query_meerkatD.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "query_meerkat - Win32 Release"
+# Name "query_meerkat - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\examples\query-meerkat.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Windows/query_meerkat.vcproj b/Windows/query_meerkat.vcproj
new file mode 100644 (file)
index 0000000..4159629
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="query_meerkat"\r
+       SccProjectName="query_meerkat"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\query_meerkat"\r
+                       IntermediateDirectory=".\Debug\query_meerkat"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpcD.lib odbc32.lib odbccp32.lib WinInet.lib"\r
+                               OutputFile="../Bin/$(ProjectName)D.exe"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Debug\query_meerkat/query_meerkat.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release\query_meerkat"\r
+                       IntermediateDirectory=".\Release\query_meerkat"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpc.lib odbc32.lib odbccp32.lib WinInet.lib"\r
+                               OutputFile="../Bin/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Release\query_meerkat/query_meerkat.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath="..\examples\query-meerkat.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/rpctest.dsp b/Windows/rpctest.dsp
new file mode 100644 (file)
index 0000000..f47498b
--- /dev/null
@@ -0,0 +1,236 @@
+# Microsoft Developer Studio Project File - Name="rpctest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=rpctest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "rpctest.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "rpctest.mak" CFG="rpctest - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "rpctest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rpctest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "rpctest"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "rpctest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\rpctest"
+# PROP Intermediate_Dir "Release\rpctest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /I "../lib/util/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\rpctest.exe"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copy test files
+PostBuild_Cmds=copy ..\src\testdata\*.* .
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "rpctest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\rpctest"
+# PROP Intermediate_Dir "Debug\rpctest"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\include" /I "../lib/util/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\rpctestD.exe" /pdbtype:sept
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copy test files
+PostBuild_Cmds=copy ..\src\testdata\*.* .
+# End Special Build Tool
+
+!ENDIF 
+
+# Begin Target
+
+# Name "rpctest - Win32 Release"
+# Name "rpctest - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\src\test\cgi.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\client.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\conf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\conn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\data.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\http.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\parse_xml.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\serialize.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\server.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\server_abyss.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\test.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\thread.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\token.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\token.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\trace.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\value.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\xml_data.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_server_abyss.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\src\test\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\parse_xml.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\serialize.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\server_abyss.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\test.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\value.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\test\xml_data.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "TestFiles"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\src\testdata\http-req-simple.txt"
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\testdata\req_no_params.xml
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\testdata\req_out_of_order.xml
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\testdata\req_value_name.xml
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Windows/rpctest.vcproj b/Windows/rpctest.vcproj
new file mode 100644 (file)
index 0000000..90b53b3
--- /dev/null
@@ -0,0 +1,574 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="rpctest"\r
+       SccProjectName="rpctest"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\rpctest"\r
+                       IntermediateDirectory=".\Debug\rpctest"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../..,..,../include,../lib/util/include"\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;ABYSS_WIN32"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpcD.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib"\r
+                               OutputFile="../Bin/$(ProjectName)D.exe"\r
+                               LinkIncremental="0"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               GenerateMapFile="FALSE"\r
+                               MapFileName=".\Debug\rpctest.map"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName="rpctest.tlb"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               Description="Copy test files"\r
+                               CommandLine="if not exist $(OutDir)\data md $(OutDir)\data"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="../Bin"\r
+                       IntermediateDirectory=".\Release\rpctest"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;ABYSS_WIN32"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpc.lib odbc32.lib odbccp32.lib Ws2_32.lib Wininet.lib"\r
+                               OutputFile="../Bin/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Release\rpctest/rpctest.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                               Description="Copy test files"\r
+                               CommandLine="if not exist $(OutDir)\data md $(OutDir)\data"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath="..\src\test\cgi.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\client.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\conf.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\conn.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\data.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\file.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\http.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\method_registry.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\parse_xml.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\serialize.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\server.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\server_abyss.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\socket.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\test.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\token.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\token.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\trace.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\value.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\xml_data.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_server_abyss.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+                       <File\r
+                               RelativePath="..\src\test\client.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\parse_xml.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\serialize.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\server_abyss.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\test.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\value.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\test\xml_data.h">\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="TestFiles"\r
+                       Filter="">\r
+                       <File\r
+                               RelativePath="..\src\testdata\http-req-simple.txt">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\testdata\req_no_params.xml">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\testdata\req_out_of_order.xml">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\testdata\req_value_name.xml">\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/transport_config_win32.h b/Windows/transport_config_win32.h
new file mode 100644 (file)
index 0000000..09f1ca9
--- /dev/null
@@ -0,0 +1,26 @@
+#define MUST_BUILD_WININET_CLIENT 1
+#define MUST_BUILD_CURL_CLIENT 0
+#define MUST_BUILD_LIBWWW_CLIENT 0
+static const char * const XMLRPC_DEFAULT_TRANSPORT = "wininet";
+
+/* 
+Set to zero if you do not wish to build the http.sys
+based XMLRPC-C Server
+*/
+#define MUST_BUILD_HTTP_SYS_SERVER 1
+
+/*
+We use pragma statements to tell the linker what we need to link with.
+Since Curl requires Winsock, Winmm, and libcurl, and no other
+project does, if we are building curl support we tell the linker
+what libs we need to add.
+*/
+#if MUST_BUILD_CURL_CLIENT > 0
+#ifdef _DEBUG
+#pragma comment( lib, "../lib/libcurld.lib" )
+#else
+#pragma comment( lib, "../lib/libcurl.lib" )
+#endif
+#pragma comment( lib, "Winmm.lib" )
+#pragma comment( lib, "Ws2_32.lib" )
+#endif
\ No newline at end of file
diff --git a/Windows/win32_config.h b/Windows/win32_config.h
new file mode 100644 (file)
index 0000000..6aaadb0
--- /dev/null
@@ -0,0 +1,2 @@
+#include "xmlrpc_config.h"\r
+\r
diff --git a/Windows/xmlrpc.dsp b/Windows/xmlrpc.dsp
new file mode 100644 (file)
index 0000000..9182914
--- /dev/null
@@ -0,0 +1,258 @@
+# Microsoft Developer Studio Project File - Name="xmlrpc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmlrpc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc.mak" CFG="xmlrpc - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xmlrpc - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmlrpc - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "xmlrpc"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "xmlrpc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlrpc"
+# PROP Intermediate_Dir "Release\xmlrpc"
+# PROP Target_Dir ""
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../lib/" /I "../lib/curl_transport" /I "../lib/util/include" /I "../include" /I "../" /I "../lib/expat/xmlparse" /I "../lib/w3c-libwww-5.3.2/Library/src" /I "../lib/abyss/src" /I "../lib/wininet_transport" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlrpc.lib"
+
+!ELSEIF  "$(CFG)" == "xmlrpc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlrpc"
+# PROP Intermediate_Dir "Debug\xmlrpc"
+# PROP Target_Dir ""
+MTL=midl.exe
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../lib/" /I "../lib/curl_transport" /I "../lib/util/include" /I "../include" /I "../" /I "../lib/expat/xmlparse" /I "../lib/w3c-libwww-5.3.2/Library/src" /I "../lib/abyss/src" /I "../lib/wininet_transport" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ABYSS_WIN32" /D "CURL_STATICLIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\xmlrpcD.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xmlrpc - Win32 Release"
+# Name "xmlrpc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;cc"
+# Begin Source File
+
+SOURCE=..\lib\util\casprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\pthreadx_win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_array.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_authcookie.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_builddecomp.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_client.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\curl_transport\xmlrpc_curl_transport.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_data.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_datetime.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_expat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_libxml2.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_parse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_registry.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_serialize.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_server_abyss.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_server_w32httpsys.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_struct.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_strutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_support.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\xmlrpc_utf8.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\wininet_transport\xmlrpc_wininet_transport.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\abyss.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\base.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\bool.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\client.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\client_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\mallocvar.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\util\include\pthreadx.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\server.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\server_abyss.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\server_cgi.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\server_w32httpsys.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\transport.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\transport_config.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\transport_int.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\xmlrpc-c\xmlparser.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\xmlrpc_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\curl_transport\xmlrpc_curl_transport.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\wininet_transport\xmlrpc_wininet_transport.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Windows/xmlrpc.dsw b/Windows/xmlrpc.dsw
new file mode 100644 (file)
index 0000000..b98b772
--- /dev/null
@@ -0,0 +1,194 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "cpptest"=".\cpptest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlrpc
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "gennmtab"="..\lib\expat\gennmtab\gennmtab.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "query_meerkat"=".\query_meerkat.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlrpc
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "rpctest"=".\rpctest.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlrpc
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlparse"="..\lib\expat\xmlparse\xmlparse.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmltok
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc"=".\xmlrpc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlparse
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_add_asynch_client"=".\xmlrpc_sample_add_asynch_client.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlrpc
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_add_server"=".\xmlrpc_sample_add_server.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlrpc
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_add_server_w32httpsys"=".\xmlrpc_sample_add_server_w32httpsys.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlrpc
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_add_sync_client"=".\xmlrpc_sample_add_sync_client.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlrpc
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmlrpc_sample_auth_client"=".\xmlrpc_sample_auth_client.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name xmlrpc
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "xmltok"="..\lib\expat\xmltok\xmltok.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name gennmtab
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Windows/xmlrpc.sln b/Windows/xmlrpc.sln
new file mode 100644 (file)
index 0000000..635a409
--- /dev/null
@@ -0,0 +1,229 @@
+Microsoft Visual Studio Solution File, Format Version 8.00\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "all", "all.vcproj", "{5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC} = {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}\r
+               {4137D986-8134-44FB-A482-50CC046CC450} = {4137D986-8134-44FB-A482-50CC046CC450}\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05} = {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA} = {3D641981-D76D-412B-AD0F-EC2CF58611AA}\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC} = {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "configwin32", "configwin32.vcproj", "{E5089B87-0C26-47A9-B758-CC0C718F7987}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpptest", "cpptest.vcproj", "{2040C78A-0231-4C59-BBD7-61DB95FA85B1}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79} = {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gennmtab", "..\lib\expat\gennmtab\gennmtab.vcproj", "{9E017925-D88F-46A2-892F-EF1FCCAE170F}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987} = {E5089B87-0C26-47A9-B758-CC0C718F7987}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "query_meerkat", "query_meerkat.vcproj", "{6DF77399-72AE-4155-A30D-7AEFF8A0A914}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79} = {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpctest", "rpctest.vcproj", "{D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79} = {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlparse", "..\lib\expat\xmlparse\xmlparse.vcproj", "{401073F1-642F-4CE3-B38E-6F5321758C93}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948} = {D9B03722-EA42-40C7-A1A8-01282B600948}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc", "xmlrpc.vcproj", "{26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93} = {401073F1-642F-4CE3-B38E-6F5321758C93}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc_sample_add_asynch_client", "xmlrpc_sample_add_asynch_client.vcproj", "{D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79} = {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc_sample_add_server", "xmlrpc_sample_add_server.vcproj", "{3D641981-D76D-412B-AD0F-EC2CF58611AA}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79} = {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc_sample_add_server_w32httpsys", "xmlrpc_sample_add_server_w32httpsys.vcproj", "{80160353-BE0D-463C-A87A-BBFBD977DB3B}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79} = {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc_sample_add_sync_client", "xmlrpc_sample_add_sync_client.vcproj", "{77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79} = {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlrpc_sample_auth_client", "xmlrpc_sample_auth_client.vcproj", "{4137D986-8134-44FB-A482-50CC046CC450}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79} = {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}\r
+       EndProjectSection\r
+EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmltok", "..\lib\expat\xmltok\xmltok.vcproj", "{D9B03722-EA42-40C7-A1A8-01282B600948}"\r
+       ProjectSection(ProjectDependencies) = postProject\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F} = {9E017925-D88F-46A2-892F-EF1FCCAE170F}\r
+       EndProjectSection\r
+EndProject\r
+Global\r
+       GlobalSection(SolutionConfiguration) = preSolution\r
+               Debug = Debug\r
+               Debug DLL = Debug DLL\r
+               MinSize DLL = MinSize DLL\r
+               Release = Release\r
+               Release DLL = Release DLL\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfiguration) = postSolution\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.Debug.ActiveCfg = Debug|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.Debug.Build.0 = Debug|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.Debug DLL.Build.0 = Debug|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.MinSize DLL.Build.0 = Release|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.Release.ActiveCfg = Release|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.Release.Build.0 = Release|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.Release DLL.ActiveCfg = Release|Win32\r
+               {5CB3B96A-1CFF-49AD-AF5F-35203E0492F2}.Release DLL.Build.0 = Release|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.Debug.ActiveCfg = Debug|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.Debug.Build.0 = Debug|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.Debug DLL.Build.0 = Debug|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.MinSize DLL.Build.0 = Release|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.Release.ActiveCfg = Release|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.Release.Build.0 = Release|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.Release DLL.ActiveCfg = Release|Win32\r
+               {E5089B87-0C26-47A9-B758-CC0C718F7987}.Release DLL.Build.0 = Release|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.Debug.ActiveCfg = Debug|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.Debug.Build.0 = Debug|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.Debug DLL.Build.0 = Debug|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.MinSize DLL.ActiveCfg = Debug|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.MinSize DLL.Build.0 = Debug|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.Release.ActiveCfg = Release|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.Release.Build.0 = Release|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.Release DLL.ActiveCfg = Release|Win32\r
+               {2040C78A-0231-4C59-BBD7-61DB95FA85B1}.Release DLL.Build.0 = Release|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.Debug.ActiveCfg = Debug|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.Debug.Build.0 = Debug|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.Debug DLL.Build.0 = Debug|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.MinSize DLL.Build.0 = Release|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.Release.ActiveCfg = Release|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.Release.Build.0 = Release|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.Release DLL.ActiveCfg = Release|Win32\r
+               {9E017925-D88F-46A2-892F-EF1FCCAE170F}.Release DLL.Build.0 = Release|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.Debug.ActiveCfg = Debug|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.Debug.Build.0 = Debug|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.Debug DLL.Build.0 = Debug|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.MinSize DLL.Build.0 = Release|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.Release.ActiveCfg = Release|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.Release.Build.0 = Release|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.Release DLL.ActiveCfg = Release|Win32\r
+               {6DF77399-72AE-4155-A30D-7AEFF8A0A914}.Release DLL.Build.0 = Release|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.Debug.ActiveCfg = Debug|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.Debug.Build.0 = Debug|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.Debug DLL.Build.0 = Debug|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.MinSize DLL.Build.0 = Release|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.Release.ActiveCfg = Release|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.Release.Build.0 = Release|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.Release DLL.ActiveCfg = Release|Win32\r
+               {D50B8203-D6C2-4EC9-907C-F01A3BDA71AC}.Release DLL.Build.0 = Release|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.Debug.ActiveCfg = Debug|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.Debug.Build.0 = Debug|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.Debug DLL.ActiveCfg = Debug DLL|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.Debug DLL.Build.0 = Debug DLL|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.MinSize DLL.ActiveCfg = MinSize DLL|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.MinSize DLL.Build.0 = MinSize DLL|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.Release.ActiveCfg = Release|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.Release.Build.0 = Release|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.Release DLL.ActiveCfg = Release DLL|Win32\r
+               {401073F1-642F-4CE3-B38E-6F5321758C93}.Release DLL.Build.0 = Release DLL|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.Debug.ActiveCfg = Debug|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.Debug.Build.0 = Debug|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.Debug DLL.Build.0 = Debug|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.MinSize DLL.Build.0 = Release|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.Release.ActiveCfg = Release|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.Release.Build.0 = Release|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.Release DLL.ActiveCfg = Release|Win32\r
+               {26FCCB92-53CA-40F3-AC9F-2EFFC745BD79}.Release DLL.Build.0 = Release|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.Debug.ActiveCfg = Debug|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.Debug.Build.0 = Debug|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.Debug DLL.Build.0 = Debug|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.MinSize DLL.Build.0 = Release|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.Release.ActiveCfg = Release|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.Release.Build.0 = Release|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.Release DLL.ActiveCfg = Release|Win32\r
+               {D6CF56C7-5E6D-4C9E-A81C-F3EEE29951AC}.Release DLL.Build.0 = Release|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.Debug.ActiveCfg = Debug|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.Debug.Build.0 = Debug|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.Debug DLL.Build.0 = Debug|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.MinSize DLL.ActiveCfg = Debug|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.MinSize DLL.Build.0 = Debug|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.Release.ActiveCfg = Release|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.Release.Build.0 = Release|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.Release DLL.ActiveCfg = Release|Win32\r
+               {3D641981-D76D-412B-AD0F-EC2CF58611AA}.Release DLL.Build.0 = Release|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.Debug.ActiveCfg = Debug|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.Debug.Build.0 = Debug|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.Debug DLL.Build.0 = Debug|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.MinSize DLL.Build.0 = Release|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.Release.ActiveCfg = Release|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.Release.Build.0 = Release|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.Release DLL.ActiveCfg = Release|Win32\r
+               {80160353-BE0D-463C-A87A-BBFBD977DB3B}.Release DLL.Build.0 = Release|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.Debug.ActiveCfg = Debug|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.Debug.Build.0 = Debug|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.Debug DLL.Build.0 = Debug|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.MinSize DLL.ActiveCfg = Release|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.MinSize DLL.Build.0 = Release|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.Release.ActiveCfg = Release|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.Release.Build.0 = Release|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.Release DLL.ActiveCfg = Release|Win32\r
+               {77DEDE54-768E-4ECA-9B2C-EF57ADFC0A05}.Release DLL.Build.0 = Release|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.Debug.ActiveCfg = Debug|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.Debug.Build.0 = Debug|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.Debug DLL.ActiveCfg = Debug|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.Debug DLL.Build.0 = Debug|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.MinSize DLL.ActiveCfg = Debug|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.MinSize DLL.Build.0 = Debug|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.Release.ActiveCfg = Release|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.Release.Build.0 = Release|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.Release DLL.ActiveCfg = Release|Win32\r
+               {4137D986-8134-44FB-A482-50CC046CC450}.Release DLL.Build.0 = Release|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.Debug.ActiveCfg = Debug|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.Debug.Build.0 = Debug|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.Debug DLL.ActiveCfg = Debug DLL|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.Debug DLL.Build.0 = Debug DLL|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.MinSize DLL.ActiveCfg = Debug DLL|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.MinSize DLL.Build.0 = Debug DLL|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.Release.ActiveCfg = Release|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.Release.Build.0 = Release|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.Release DLL.ActiveCfg = Release DLL|Win32\r
+               {D9B03722-EA42-40C7-A1A8-01282B600948}.Release DLL.Build.0 = Release DLL|Win32\r
+       EndGlobalSection\r
+       GlobalSection(ExtensibilityGlobals) = postSolution\r
+       EndGlobalSection\r
+       GlobalSection(ExtensibilityAddIns) = postSolution\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/Windows/xmlrpc.vcproj b/Windows/xmlrpc.vcproj
new file mode 100644 (file)
index 0000000..6a6804c
--- /dev/null
@@ -0,0 +1,1013 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="xmlrpc"\r
+       SccProjectName="xmlrpc"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\xmlrpc"\r
+                       IntermediateDirectory=".\Debug\xmlrpc"\r
+                       ConfigurationType="4"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.lib;*.exp;*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="../lib,../lib/curl_transport,../lib/util/include,../include,..,../lib/expat/xmlparse,../lib/abyss/src,../lib/wininet_transport,../.."\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="4"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="..\lib\xmlrpcD.lib"\r
+                               SuppressStartupBanner="TRUE"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release\xmlrpc"\r
+                       IntermediateDirectory=".\Release\xmlrpc"\r
+                       ConfigurationType="4"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.lib;*.exp;*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="../lib,../lib/curl_transport,../lib/util/include,../include,..,../lib/expat/xmlparse,../lib/abyss/src,../lib/wininet_transport,../.."\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLibrarianTool"\r
+                               OutputFile="..\lib\xmlrpc.lib"\r
+                               SuppressStartupBanner="TRUE"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;cc">\r
+                       <File\r
+                               RelativePath="..\lib\libutil\casprintf.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\date.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\libutil\error.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\libutil\make_printable.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\libutil\memblock.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\libutil\MemLeakCheck.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\util\pthreadx_win32.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\registry.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\libutil\resource.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\response.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\session.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\libutil\sleep.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\socket_win.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\system_method.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\thread_windows.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\token.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\trace.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\libutil\xml_rpc_alloc.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_array.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_authcookie.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_base64.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_builddecomp.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_client.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_client_global.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\curl_transport\xmlrpc_curl_transport.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_data.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_datetime.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_expat.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_libxml2.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_parse.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_registry.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_serialize.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_server_abyss.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_server_w32httpsys.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_struct.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_strutil.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_support.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       ExcludedFromBuild="TRUE">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\src\xmlrpc_utf8.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\wininet_transport\xmlrpc_wininet_transport.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\abyss.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\base.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\util\include\bool.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\client.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\client_int.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\util\include\mallocvar.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\util\include\pthreadx.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\server.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\server_abyss.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\server_cgi.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\server_w32httpsys.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\transport.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\transport_config.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\transport_int.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\include\xmlrpc-c\xmlparser.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\xmlrpc_config.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\curl_transport\xmlrpc_curl_transport.h">\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\wininet_transport\xmlrpc_wininet_transport.h">\r
+                       </File>\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/xmlrpc_sample_add_asynch_client.dsp b/Windows/xmlrpc_sample_add_asynch_client.dsp
new file mode 100644 (file)
index 0000000..91e63a8
--- /dev/null
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_asynch_client" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_add_asynch_client - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_add_asynch_client.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_add_asynch_client.mak" CFG="xmlrpc_sample_add_asynch_client - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xmlrpc_sample_add_asynch_client - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_add_asynch_client - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "xmlrpc_sample_add_asynch_client"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "xmlrpc_sample_add_asynch_client - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlrpc_sample_add_asynch_client"
+# PROP Intermediate_Dir "Release\xmlrpc_sample_add_asynch_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib WinInet.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_asynch_client.exe"
+
+!ELSEIF  "$(CFG)" == "xmlrpc_sample_add_asynch_client - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlrpc_sample_add_asynch_client"
+# PROP Intermediate_Dir "Debug\xmlrpc_sample_add_asynch_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpcD.lib WinInet.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_asynch_clientD.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xmlrpc_sample_add_asynch_client - Win32 Release"
+# Name "xmlrpc_sample_add_asynch_client - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\xmlrpc_asynch_client.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Windows/xmlrpc_sample_add_asynch_client.vcproj b/Windows/xmlrpc_sample_add_asynch_client.vcproj
new file mode 100644 (file)
index 0000000..9576b6c
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="xmlrpc_sample_add_asynch_client"\r
+       SccProjectName="xmlrpc_sample_add_asynch_client"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\xmlrpc_sample_add_asynch_client"\r
+                       IntermediateDirectory=".\Debug\xmlrpc_sample_add_asynch_client"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpcD.lib WinInet.lib odbc32.lib odbccp32.lib"\r
+                               OutputFile="../Bin/$(ProjectName)D.exe"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Debug\xmlrpc_sample_add_asynch_client/xmlrpc_sample_add_asynch_client.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release\xmlrpc_sample_add_asynch_client"\r
+                       IntermediateDirectory=".\Release\xmlrpc_sample_add_asynch_client"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpc.lib WinInet.lib odbc32.lib odbccp32.lib"\r
+                               OutputFile="../Bin/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Release\xmlrpc_sample_add_asynch_client/xmlrpc_sample_add_asynch_client.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath="..\examples\xmlrpc_asynch_client.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/xmlrpc_sample_add_server.dsp b/Windows/xmlrpc_sample_add_server.dsp
new file mode 100644 (file)
index 0000000..abb8127
--- /dev/null
@@ -0,0 +1,140 @@
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_server" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_add_server - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_add_server.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_add_server.mak" CFG="xmlrpc_sample_add_server - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xmlrpc_sample_add_server - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_add_server - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "xmlrpc_sample_add_server"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "xmlrpc_sample_add_server - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release\xmlrpc_sample_add_server"
+# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_server"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpc.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_server.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "xmlrpc_sample_add_server - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug\xmlrpc_sample_add_server"
+# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_server"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpcD.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_serverD.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xmlrpc_sample_add_server - Win32 Release"
+# Name "xmlrpc_sample_add_server - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\conf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\conn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\data.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\http.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\server.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\thread.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib\abyss\src\trace.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\examples\xmlrpc_sample_add_server.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Windows/xmlrpc_sample_add_server.vcproj b/Windows/xmlrpc_sample_add_server.vcproj
new file mode 100644 (file)
index 0000000..2168061
--- /dev/null
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="xmlrpc_sample_add_server"\r
+       SccProjectName="xmlrpc_sample_add_server"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release\xmlrpc_sample_add_server"\r
+                       IntermediateDirectory=".\Release\xmlrpc_sample_add_server"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;ABYSS_WIN32;_THREAD"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpc.lib ws2_32.lib"\r
+                               OutputFile="../Bin/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Release\xmlrpc_sample_add_server/xmlrpc_sample_add_server.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\xmlrpc_sample_add_server"\r
+                       IntermediateDirectory=".\Debug\xmlrpc_sample_add_server"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;ABYSS_WIN32;_THREAD"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               BrowseInformation="1"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpcD.lib ws2_32.lib"\r
+                               OutputFile="../Bin/$(ProjectName)D.exe"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Debug\xmlrpc_sample_add_server/xmlrpc_sample_add_server.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\conf.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\conn.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\data.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\file.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\http.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\server.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\socket.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\lib\abyss\src\trace.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\examples\xmlrpc_sample_add_server.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"\r
+                                               BrowseInformation="1"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/xmlrpc_sample_add_server_w32httpsys.dsp b/Windows/xmlrpc_sample_add_server_w32httpsys.dsp
new file mode 100644 (file)
index 0000000..c716f3f
--- /dev/null
@@ -0,0 +1,104 @@
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_server_w32httpsys" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_add_server_w32httpsys - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_add_server_w32httpsys.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_add_server_w32httpsys.mak" CFG="xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xmlrpc_sample_add_server_w32httpsys - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_add_server_w32httpsys - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "xmlrpc_sample_add_server_w32httpsys"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "xmlrpc_sample_add_server_w32httpsys - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release\xmlrpc_sample_add_server_w32httpsys"
+# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_server_w32httpsys"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpc.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_server_w32httpsys.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug\xmlrpc_sample_add_server_w32httpsys"
+# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_server_w32httpsys"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /D "_THREAD" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib ..\lib\xmlrpcD.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_server_w32httpsysD.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xmlrpc_sample_add_server_w32httpsys - Win32 Release"
+# Name "xmlrpc_sample_add_server_w32httpsys - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\xmlrpc_sample_add_server_w32httpsys.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Windows/xmlrpc_sample_add_server_w32httpsys.vcproj b/Windows/xmlrpc_sample_add_server_w32httpsys.vcproj
new file mode 100644 (file)
index 0000000..620f24b
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="xmlrpc_sample_add_server_w32httpsys"\r
+       SccProjectName="xmlrpc_sample_add_server_w32httpsys"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\xmlrpc_sample_add_server_w32httpsys"\r
+                       IntermediateDirectory=".\Debug\xmlrpc_sample_add_server_w32httpsys"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;ABYSS_WIN32;_THREAD"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpcD.lib ws2_32.lib"\r
+                               OutputFile="../Bin/$(ProjectName)D.exe"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Debug\xmlrpc_sample_add_server_w32httpsys/xmlrpc_sample_add_server_w32httpsys.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release\xmlrpc_sample_add_server_w32httpsys"\r
+                       IntermediateDirectory=".\Release\xmlrpc_sample_add_server_w32httpsys"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;ABYSS_WIN32;_THREAD"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpc.lib ws2_32.lib"\r
+                               OutputFile="../Bin/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Release\xmlrpc_sample_add_server_w32httpsys/xmlrpc_sample_add_server_w32httpsys.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath="..\examples\xmlrpc_sample_add_server_w32httpsys.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/xmlrpc_sample_add_sync_client.dsp b/Windows/xmlrpc_sample_add_sync_client.dsp
new file mode 100644 (file)
index 0000000..c784456
--- /dev/null
@@ -0,0 +1,104 @@
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_add_sync_client" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_add_sync_client - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_add_sync_client.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_add_sync_client.mak" CFG="xmlrpc_sample_add_sync_client - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xmlrpc_sample_add_sync_client - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_add_sync_client - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "xmlrpc_sample_add_sync_client"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "xmlrpc_sample_add_sync_client - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release\xmlrpc_sample_add_sync_client"
+# PROP Intermediate_Dir ".\Release\xmlrpc_sample_add_sync_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_add_sync_client.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "xmlrpc_sample_add_sync_client - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug\xmlrpc_sample_add_sync_client"
+# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_add_sync_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_add_sync_clientD.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xmlrpc_sample_add_sync_client - Win32 Release"
+# Name "xmlrpc_sample_add_sync_client - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\xmlrpc_sample_add_client.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Windows/xmlrpc_sample_add_sync_client.vcproj b/Windows/xmlrpc_sample_add_sync_client.vcproj
new file mode 100644 (file)
index 0000000..b280a52
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="xmlrpc_sample_add_sync_client"\r
+       SccProjectName="xmlrpc_sample_add_sync_client"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\xmlrpc_sample_add_sync_client"\r
+                       IntermediateDirectory=".\Debug\xmlrpc_sample_add_sync_client"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpcD.lib WinInet.lib"\r
+                               OutputFile="../Bin/$(ProjectName)D.exe"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Debug\xmlrpc_sample_add_sync_client/xmlrpc_sample_add_sync_client.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release\xmlrpc_sample_add_sync_client"\r
+                       IntermediateDirectory=".\Release\xmlrpc_sample_add_sync_client"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpc.lib WinInet.lib"\r
+                               OutputFile="../Bin/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Release\xmlrpc_sample_add_sync_client/xmlrpc_sample_add_sync_client.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath="..\examples\xmlrpc_sample_add_client.c">\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/xmlrpc_sample_auth_client.dsp b/Windows/xmlrpc_sample_auth_client.dsp
new file mode 100644 (file)
index 0000000..6edd252
--- /dev/null
@@ -0,0 +1,104 @@
+# Microsoft Developer Studio Project File - Name="xmlrpc_sample_auth_client" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=xmlrpc_sample_auth_client - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_auth_client.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlrpc_sample_auth_client.mak" CFG="xmlrpc_sample_auth_client - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xmlrpc_sample_auth_client - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "xmlrpc_sample_auth_client - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "xmlrpc_sample_auth_client"
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "xmlrpc_sample_auth_client - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\Release\xmlrpc_sample_auth_client"
+# PROP Intermediate_Dir ".\Release\xmlrpc_sample_auth_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ..\lib\xmlrpc.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlrpc_sample_auth_client.exe"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "xmlrpc_sample_auth_client - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\Debug\xmlrpc_sample_auth_client"
+# PROP Intermediate_Dir ".\Debug\xmlrpc_sample_auth_client"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\\" /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ..\lib\xmlrpcD.lib kernel32.lib user32.lib gdi32.lib WinInet.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\xmlrpc_sample_auth_clientD.exe" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xmlrpc_sample_auth_client - Win32 Release"
+# Name "xmlrpc_sample_auth_client - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\examples\auth_client.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Windows/xmlrpc_sample_auth_client.vcproj b/Windows/xmlrpc_sample_auth_client.vcproj
new file mode 100644 (file)
index 0000000..f61e10d
--- /dev/null
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="7.10"\r
+       Name="xmlrpc_sample_auth_client"\r
+       SccProjectName="xmlrpc_sample_auth_client"\r
+       SccLocalPath="..">\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"/>\r
+       </Platforms>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       OutputDirectory=".\Release\xmlrpc_sample_auth_client"\r
+                       IntermediateDirectory=".\Release\xmlrpc_sample_auth_client"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="2"\r
+                               InlineFunctionExpansion="1"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE"\r
+                               StringPooling="TRUE"\r
+                               RuntimeLibrary="0"\r
+                               EnableFunctionLevelLinking="TRUE"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpc.lib WinInet.lib"\r
+                               OutputFile="../Bin/$(ProjectName).exe"\r
+                               LinkIncremental="1"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Release\xmlrpc_sample_auth_client/xmlrpc_sample_auth_client.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="NDEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       OutputDirectory=".\Debug\xmlrpc_sample_auth_client"\r
+                       IntermediateDirectory=".\Debug\xmlrpc_sample_auth_client"\r
+                       ConfigurationType="1"\r
+                       UseOfMFC="0"\r
+                       ATLMinimizesCRunTimeLibraryUsage="FALSE"\r
+                       CharacterSet="2"\r
+                       DeleteExtensionsOnClean="*.obj;*.ilk;*.pdb;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.bat;$(TargetPath)">\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
+                               AdditionalIncludeDirectories="..,../include,../lib/util/include,../.."\r
+                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
+                               UsePrecompiledHeader="2"\r
+                               WarningLevel="3"\r
+                               SuppressStartupBanner="TRUE"\r
+                               DebugInformationFormat="3"\r
+                               CompileAs="0"/>\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"/>\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               AdditionalDependencies="..\lib\xmlrpcD.lib WinInet.lib"\r
+                               OutputFile="../Bin/$(ProjectName)D.exe"\r
+                               SuppressStartupBanner="TRUE"\r
+                               GenerateDebugInformation="TRUE"\r
+                               ProgramDatabaseFile="$(TargetDir)/$(TargetName).pdb"\r
+                               SubSystem="1"\r
+                               TargetMachine="1"/>\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TypeLibraryName=".\Debug\xmlrpc_sample_auth_client/xmlrpc_sample_auth_client.tlb"\r
+                               HeaderFileName=""/>\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"/>\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"/>\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                               PreprocessorDefinitions="_DEBUG"\r
+                               Culture="1033"/>\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCWebDeploymentTool"/>\r
+                       <Tool\r
+                               Name="VCManagedWrapperGeneratorTool"/>\r
+                       <Tool\r
+                               Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter\r
+                       Name="Source Files"\r
+                       Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">\r
+                       <File\r
+                               RelativePath="..\examples\auth_client.c">\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="2"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""/>\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32">\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               Optimization="0"\r
+                                               AdditionalIncludeDirectories=""\r
+                                               PreprocessorDefinitions=""\r
+                                               BasicRuntimeChecks="3"/>\r
+                               </FileConfiguration>\r
+                       </File>\r
+               </Filter>\r
+               <Filter\r
+                       Name="Header Files"\r
+                       Filter="h;hpp;hxx;hm;inl">\r
+               </Filter>\r
+               <Filter\r
+                       Name="Resource Files"\r
+                       Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/Windows/xmlrpc_win32_config.h b/Windows/xmlrpc_win32_config.h
new file mode 100644 (file)
index 0000000..a84eead
--- /dev/null
@@ -0,0 +1,130 @@
+#pragma once
+
+/* From xmlrpc_amconfig.h */
+  
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+/* #undef size_t */
+
+/* Define if you have the setgroups function.  */
+/* #undef HAVE_SETGROUPS */
+
+/* #undef HAVE_ASPRINTF */
+
+/* Define if you have the wcsncmp function.  */
+#define HAVE_WCSNCMP 1
+
+/* Define if you have the <stdarg.h> header file.  */
+#define HAVE_STDARG_H 1
+
+#define HAVE_SYS_FILIO_H 0
+
+#define HAVE_SYS_IOCTL_H 0
+
+/* Define if you have the <wchar.h> header file.  */
+#define HAVE_WCHAR_H 1
+
+/* Define if you have the socket library (-lsocket).  */
+/* #undef HAVE_LIBSOCKET */
+
+/* Name of package */
+#define PACKAGE "xmlrpc-c"
+
+
+/* Win32 version of xmlrpc_config.h
+
+   Logical macros are 0 or 1 instead of the more traditional defined and
+   undefined.  That's so we can distinguish when compiling code between
+   "false" and some problem with the code.
+*/
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+/* Define if va_list is actually an array. */
+#define VA_LIST_IS_ARRAY 0
+  
+/* Define if we're using a copy of libwww with built-in SSL support. */
+#define HAVE_LIBWWW_SSL 0
+
+/* Used to mark unused variables under GCC... */
+#define ATTR_UNUSED
+
+#define HAVE_UNICODE_WCHAR
+  
+#define DIRECTORY_SEPARATOR "\\"
+
+  
+/* Windows-specific includes. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined (vsnprintf)
+  #define vsnprintf _vsnprintf
+#endif
+#if !defined (snprintf)
+  #define snprintf _snprintf
+#endif
+#if !defined (popen) 
+  #define popen _popen
+#endif
+
+
+#include <time.h>
+#include <WINSOCK.h>
+#include <direct.h>  /* for _chdir() */
+
+/* We are linking against the multithreaded versions
+   of the Microsoft runtimes - this makes gmtime 
+   equiv to gmtime_r in that Windows gmtime is threadsafe
+*/
+#if !defined (gmtime_r)
+static struct tm* gmtime_r(const time_t *timep, struct tm* result)
+{
+       struct tm *local;
+
+       local = gmtime(timep);
+       memcpy(result,local,sizeof(struct tm));
+       return result;
+}
+
+#endif
+
+#ifndef socklen_t
+typedef unsigned int socklen_t;
+#endif
+
+/* inttypes.h */
+#ifndef int8_t
+typedef signed char       int8_t;
+#endif
+#ifndef uint8_t
+typedef unsigned char     uint8_t;
+#endif
+#ifndef int16_t
+typedef signed short      int16_t;
+#endif
+#ifndef uint16_t
+typedef unsigned short    uint16_t;
+#endif
+#ifndef int32_t
+typedef signed int        int32_t;
+#endif
+#ifndef uint32_t
+typedef unsigned int      uint32_t;
+#endif
+#ifndef int64_t
+typedef __int64           int64_t;
+#endif
+#ifndef uint64_t
+typedef unsigned __int64  uint64_t;
+#endif
+
+#define __inline__ __inline
+
+#define HAVE_SETENV 1
+__inline BOOL setenv(const char* name, const char* value, int i) 
+{
+       return (SetEnvironmentVariable(name, value) != 0) ? TRUE : FALSE;
+}
+
+#define strcasecmp(a,b) stricmp((a),(b))
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..9f6a125
--- /dev/null
@@ -0,0 +1,545 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated.  We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+  case " <<$>>CONFIG_HEADERS " in
+  *" <<$>>am_file "*<<)>>
+    echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+    ;;
+  esac
+  am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+# Do all the work for Automake.  This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "[$]*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "[$]*" != "X $srcdir/configure conftestfile" \
+      && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "[$]2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+   $1=$2
+   AC_MSG_RESULT(found)
+else
+   $1="$3/missing $2"
+   AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+
+# serial 40 AC_PROG_LIBTOOL
+AC_DEFUN(AC_PROG_LIBTOOL,
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+# Save cache, so that ltconfig can load it
+AC_CACHE_SAVE
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
+LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
+DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \
+|| AC_MSG_ERROR([libtool configure failed])
+
+# Reload cache, that may have been modified by ltconfig
+AC_CACHE_LOAD
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+])
+
+AC_DEFUN(AC_LIBTOOL_SETUP,
+[AC_PREREQ(2.13)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_RANLIB])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+dnl
+
+case "$target" in
+NONE) lt_target="$host" ;;
+*) lt_target="$target" ;;
+esac
+
+# Check for any special flags to pass to ltconfig.
+#
+# the following will cause an existing older ltconfig to fail, so
+# we ignore this at the expense of the cache file... Checking this 
+# will just take longer ... bummer!
+#libtool_flags="--cache-file=$cache_file"
+#
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN],
+[libtool_flags="$libtool_flags --enable-dlopen"])
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[libtool_flags="$libtool_flags --enable-win32-dll"])
+AC_ARG_ENABLE(libtool-lock,
+  [  --disable-libtool-lock  avoid locking (might break parallel builds)])
+test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
+test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$lt_target" in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw*)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+])
+esac
+])
+
+# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
+AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
+
+# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
+AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
+
+# AC_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_SHARED, [dnl
+define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<<  --enable-shared[=PKGS]  build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)])
+
+# AC_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_STATIC, [dnl
+define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<<  --enable-static[=PKGS]  build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+])
+
+# AC_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)])
+
+
+# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl
+define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(fast-install,
+changequote(<<, >>)dnl
+<<  --enable-fast-install[=PKGS]  optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+])
+
+# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install
+AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)])
+
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN(AC_PROG_LD,
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  ac_prog=`($CC -print-prog-name=ld) 2>&5`
+  case "$ac_prog" in
+    # Accept absolute paths.
+changequote(,)dnl
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+changequote([,])dnl
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      ac_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])
+
+AC_DEFUN(AC_PROG_LD_GNU,
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  ac_cv_prog_gnu_ld=yes
+else
+  ac_cv_prog_gnu_ld=no
+fi])
+])
+
+# AC_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN(AC_PROG_NM,
+[AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(ac_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  ac_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -B"
+       break
+      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -p"
+       break
+      else
+       ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi])
+NM="$ac_cv_path_NM"
+AC_MSG_RESULT([$NM])
+])
+
+# AC_CHECK_LIBM - check for math library
+AC_DEFUN(AC_CHECK_LIBM,
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case "$lt_target" in
+*-*-beos* | *-*-cygwin*)
+  # These system don't have libm
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, main, LIBM="-lm")
+  ;;
+esac
+])
+
+# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl convenience library and INCLTDL to the include flags for
+# the libltdl header and adds --enable-ltdl-convenience to the
+# configure arguments.  Note that LIBLTDL and INCLTDL are not
+# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If DIR is not
+# provided, it is assumed to be `libltdl'.  LIBLTDL will be prefixed
+# with '${top_builddir}/' and INCLTDL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  case "$enable_ltdl_convenience" in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+  INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+])
+
+# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl installable library and INCLTDL to the include flags for
+# the libltdl header and adds --enable-ltdl-install to the configure
+# arguments.  Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is
+# AC_CONFIG_SUBDIRS called.  If DIR is not provided and an installed
+# libltdl is not found, it is assumed to be `libltdl'.  LIBLTDL will
+# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed
+# with '${top_srcdir}/' (note the single quotes!).  If your package is
+# not flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  AC_CHECK_LIB(ltdl, main,
+  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+  [if test x"$enable_ltdl_install" = xno; then
+     AC_MSG_WARN([libltdl not installed, but installation disabled])
+   else
+     enable_ltdl_install=yes
+   fi
+  ])
+  if test x"$enable_ltdl_install" = x"yes"; then
+    ac_configure_args="$ac_configure_args --enable-ltdl-install"
+    LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+    INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  else
+    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+    LIBLTDL="-lltdl"
+    INCLTDL=
+  fi
+])
+
+dnl old names
+AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl
+AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl
+AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl
+
+dnl This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])dnl
+
diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0
new file mode 100644 (file)
index 0000000..e4acf16
--- /dev/null
@@ -0,0 +1,7573 @@
+@%:@! /bin/sh
+@%:@ Guess values for system-dependent variables and create Makefiles.
+@%:@ Generated by GNU Autoconf 2.59.
+@%:@ 
+@%:@ Copyright (C) 2003 Free Software Foundation, Inc.
+@%:@ This configure script is free software; the Free Software Foundation
+@%:@ gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="include/xmlrpc-c/base.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO SET_MAKE VERSION_INFO build build_cpu build_vendor build_os host host_cpu host_vendor host_os have_wininet_config MUST_BUILD_WININET_CLIENT have_curl_config MUST_BUILD_CURL_CLIENT have_libwww_config MUST_BUILD_LIBWWW_CLIENT LIBXMLRPC_CLIENT_LA CLIENTTEST XMLRPC_CLIENT_H XMLRPC_TRANSPORT_H SYNCH_CLIENT ASYNCH_CLIENT AUTH_CLIENT QUERY_MEERKAT ENABLE_ABYSS_SERVER ABYSS_SUBDIR LIBXMLRPC_ABYSS_SERVER_LA SERVERTEST VALIDATEE XMLRPC_ABYSS_H SERVER ENABLE_CGI_SERVER ENABLE_CPLUSPLUS LIBXMLRPC_CPP_A CPPTEST XMLRPCCPP_H XML_RPC_API2CPP_SUBDIR FEATURE_LIST CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX LSOCKET CPP EGREP HAVE_WCHAR_H_DEFINE HAVE_SYS_FILIO_H_DEFINE HAVE_SYS_IOCTL_H_DEFINE VA_LIST_IS_ARRAY_DEFINE ATTR_UNUSED DIRECTORY_SEPARATOR ENABLE_ABYSS_THREADS WININET_CONFIG WININET_CFLAGS WININET_LDADD WININET_LIBDIR WININET_RPATH WININET_WL_RPATH LIBWWW_CONFIG LIBWWW_LDADD LIBWWW_LIBDIR LIBWWW_RPATH LIBWWW_WL_RPATH CURL_CONFIG CURL_LDADD CURL_LIBDIR CURL_RPATH CURL_WL_RPATH HAVE_LIBWWW_SSL_DEFINE have_xml2_config ENABLE_LIBXML2_BACKEND C_COMPILER_GNU CXX_COMPILER_GNU CC_WARN_FLAGS CPP_WARN_FLAGS BUILDDIR RANLIB ac_ct_RANLIB LN_S LIBTOOL LIB@&t@OBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+             localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$0" : 'X\(//\)[^/]' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                         [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                         [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-wininet-client  Don't build the Wininet client transport
+  --disable-curl-client     Don't build the Curl client transport
+  --disable-libwww-client   Don't build the Libwww client transport
+  --disable-abyss-server    Don't build the Abyss server module
+  --disable-cgi-server      Don't build the CGI server module
+  --disable-cplusplus       Don't build the C++ wrapper classes or tools
+  --disable-abyss-threads   Use fork in Abyss instead of pthreads
+  --enable-libxml2-backend  Use libxml2 instead of built-in expat
+  --enable-shared=PKGS  build shared libraries default=yes
+  --enable-static=PKGS  build static libraries default=yes
+  --enable-fast-install=PKGS  optimize for fast installation default=yes
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-libwww-ssl       Include libwww SSL capability.
+   
+  --with-gnu-ld           assume the C compiler uses GNU ld default=no
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+          test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+@%:@@%:@ --------- @%:@@%:@
+@%:@@%:@ Platform. @%:@@%:@
+@%:@@%:@ --------- @%:@@%:@
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+@%:@@%:@ ----------- @%:@@%:@
+@%:@@%:@ Core tests. @%:@@%:@
+@%:@@%:@ ----------- @%:@@%:@
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+@%:@@%:@ ---------------- @%:@@%:@
+@%:@@%:@ Cache variables. @%:@@%:@
+@%:@@%:@ ---------------- @%:@@%:@
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+@%:@@%:@ ----------------- @%:@@%:@
+@%:@@%:@ Output variables. @%:@@%:@
+@%:@@%:@ ----------------- @%:@@%:@
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+@%:@@%:@ ------------- @%:@@%:@
+@%:@@%:@ Output files. @%:@@%:@
+@%:@@%:@ ------------- @%:@@%:@
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=$`echo $ac_var`
+       echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+@%:@@%:@ ----------- @%:@@%:@
+@%:@@%:@ confdefs.h. @%:@@%:@
+@%:@@%:@ ----------- @%:@@%:@
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+       ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+          ac_config_headers="$ac_config_headers xmlrpc_amconfig.h"
+
+          ac_config_commands="$ac_config_commands default-1"
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "$*" != "X $srcdir/configure conftestfile" \
+      && test "$*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f conftest*
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+       @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+PACKAGE=xmlrpc-c
+
+VERSION=1.06.31
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+@%:@define VERSION "$VERSION"
+_ACEOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo "$as_me:$LINENO: checking for working aclocal" >&5
+echo $ECHO_N "checking for working aclocal... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+   ACLOCAL=aclocal
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   ACLOCAL="$missing_dir/missing aclocal"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+echo "$as_me:$LINENO: checking for working autoconf" >&5
+echo $ECHO_N "checking for working autoconf... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+   AUTOCONF=autoconf
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   AUTOCONF="$missing_dir/missing autoconf"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+echo "$as_me:$LINENO: checking for working automake" >&5
+echo $ECHO_N "checking for working automake... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+   AUTOMAKE=automake
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   AUTOMAKE="$missing_dir/missing automake"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+echo "$as_me:$LINENO: checking for working autoheader" >&5
+echo $ECHO_N "checking for working autoheader... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+   AUTOHEADER=autoheader
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   AUTOHEADER="$missing_dir/missing autoheader"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+echo "$as_me:$LINENO: checking for working makeinfo" >&5
+echo $ECHO_N "checking for working makeinfo... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+   MAKEINFO=makeinfo
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   MAKEINFO="$missing_dir/missing makeinfo"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+
+
+VERSION_INFO="-version-info 7:0:6"
+
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+
+test -z "$target" && target=NONE
+
+
+FEATURE_LIST=
+
+# Check whether --enable-wininet-client or --disable-wininet-client was given.
+if test "${enable_wininet_client+set}" = set; then
+  enableval="$enable_wininet_client"
+  
+else
+  enable_wininet_client=maybe
+fi; 
+
+if test $enable_wininet_client = maybe; then
+  # Extract the first word of "wininet-config", so it can be a program name with args.
+set dummy wininet-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_have_wininet_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$have_wininet_config"; then
+  ac_cv_prog_have_wininet_config="$have_wininet_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_wininet_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_have_wininet_config" && ac_cv_prog_have_wininet_config="no"
+fi
+fi
+have_wininet_config=$ac_cv_prog_have_wininet_config
+if test -n "$have_wininet_config"; then
+  echo "$as_me:$LINENO: result: $have_wininet_config" >&5
+echo "${ECHO_T}$have_wininet_config" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  if test $have_wininet_config = no; then
+    { echo "$as_me:$LINENO: You don't appear to have Wininet installed (no working wininet-config in your command search path), so we will not build the Wininet client XML transport" >&5
+echo "$as_me: You don't appear to have Wininet installed (no working wininet-config in your command search path), so we will not build the Wininet client XML transport" >&6;}
+    MUST_BUILD_WININET_CLIENT=no
+  else
+    MUST_BUILD_WININET_CLIENT=yes
+  fi
+else
+  MUST_BUILD_WININET_CLIENT=$enable_wininet_client
+fi
+
+echo "$as_me:$LINENO: checking whether to build Wininet client XML transport module" >&5
+echo $ECHO_N "checking whether to build Wininet client XML transport module... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $MUST_BUILD_WININET_CLIENT" >&5
+echo "${ECHO_T}$MUST_BUILD_WININET_CLIENT" >&6
+
+
+
+# Check whether --enable-curl-client or --disable-curl-client was given.
+if test "${enable_curl_client+set}" = set; then
+  enableval="$enable_curl_client"
+  
+else
+  enable_curl_client=maybe
+fi; 
+
+if test $enable_curl_client = maybe; then
+  # Extract the first word of "curl-config", so it can be a program name with args.
+set dummy curl-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_have_curl_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$have_curl_config"; then
+  ac_cv_prog_have_curl_config="$have_curl_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_curl_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_have_curl_config" && ac_cv_prog_have_curl_config="no"
+fi
+fi
+have_curl_config=$ac_cv_prog_have_curl_config
+if test -n "$have_curl_config"; then
+  echo "$as_me:$LINENO: result: $have_curl_config" >&5
+echo "${ECHO_T}$have_curl_config" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  if test $have_curl_config = no; then
+    { echo "$as_me:$LINENO: You don't appear to have Curl installed (no working curl-config in your command search path), so we will not build the Curl client XML transport" >&5
+echo "$as_me: You don't appear to have Curl installed (no working curl-config in your command search path), so we will not build the Curl client XML transport" >&6;}
+    MUST_BUILD_CURL_CLIENT=no
+  else
+    MUST_BUILD_CURL_CLIENT=yes
+  fi
+else
+  MUST_BUILD_CURL_CLIENT=$enable_curl_client
+fi
+
+echo "$as_me:$LINENO: checking whether to build Curl client XML transport module" >&5
+echo $ECHO_N "checking whether to build Curl client XML transport module... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $MUST_BUILD_CURL_CLIENT" >&5
+echo "${ECHO_T}$MUST_BUILD_CURL_CLIENT" >&6
+
+
+
+# Check whether --enable-libwww-client or --disable-libwww-client was given.
+if test "${enable_libwww_client+set}" = set; then
+  enableval="$enable_libwww_client"
+  
+else
+  enable_libwww_client=maybe
+fi; 
+
+if test $enable_libwww_client = maybe; then
+  # Extract the first word of "libwww-config", so it can be a program name with args.
+set dummy libwww-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_have_libwww_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$have_libwww_config"; then
+  ac_cv_prog_have_libwww_config="$have_libwww_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_libwww_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_have_libwww_config" && ac_cv_prog_have_libwww_config="no"
+fi
+fi
+have_libwww_config=$ac_cv_prog_have_libwww_config
+if test -n "$have_libwww_config"; then
+  echo "$as_me:$LINENO: result: $have_libwww_config" >&5
+echo "${ECHO_T}$have_libwww_config" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  if test $have_libwww_config = no; then
+    { echo "$as_me:$LINENO: You don't appear to have Libwww installed (no working libwww-config in your command search path), so we will not build the Libwww client XML transport" >&5
+echo "$as_me: You don't appear to have Libwww installed (no working libwww-config in your command search path), so we will not build the Libwww client XML transport" >&6;}
+    MUST_BUILD_LIBWWW_CLIENT=no
+  else
+    MUST_BUILD_LIBWWW_CLIENT=yes
+  fi
+else
+  MUST_BUILD_LIBWWW_CLIENT=$enable_libwww_client
+fi
+
+echo "$as_me:$LINENO: checking whether to build Libwww client XML transport module" >&5
+echo $ECHO_N "checking whether to build Libwww client XML transport module... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $MUST_BUILD_LIBWWW_CLIENT" >&5
+echo "${ECHO_T}$MUST_BUILD_LIBWWW_CLIENT" >&6
+
+
+
+if test "$MUST_BUILD_WININET_CLIENT $MUST_BUILD_CURL_CLIENT $MUST_BUILD_LIBWWW_CLIENT" = "no no no"; then
+  { echo "$as_me:$LINENO: We are not building any client XML transport, therefore we will not build the client library at all." >&5
+echo "$as_me: We are not building any client XML transport, therefore we will not build the client library at all." >&6;}
+fi
+
+
+
+LIBXMLRPC_CLIENT_LA=libxmlrpc_client.la
+
+CLIENTTEST=clienttest
+
+XMLRPC_CLIENT_H=xmlrpc_client.h
+
+XMLRPC_TRANSPORT_H=xmlrpc_transport.h
+
+SYNCH_CLIENT=synch_client
+
+ASYNCH_CLIENT=asynch_client
+
+AUTH_CLIENT=auth_client
+
+QUERY_MEERKAT=query-meerkat
+
+
+if test $MUST_BUILD_WININET_CLIENT = yes; then
+    FEATURE_LIST="wininet-client $FEATURE_LIST"
+fi
+if test $MUST_BUILD_CURL_CLIENT = yes; then
+    FEATURE_LIST="curl-client $FEATURE_LIST"
+fi
+if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+    FEATURE_LIST="libwww-client $FEATURE_LIST"
+fi
+
+echo "$as_me:$LINENO: checking whether to build Abyss server module" >&5
+echo $ECHO_N "checking whether to build Abyss server module... $ECHO_C" >&6
+# Check whether --enable-abyss-server or --disable-abyss-server was given.
+if test "${enable_abyss_server+set}" = set; then
+  enableval="$enable_abyss_server"
+  
+else
+  enable_abyss_server=yes
+fi; 
+echo "$as_me:$LINENO: result: $enable_abyss_server" >&5
+echo "${ECHO_T}$enable_abyss_server" >&6
+ENABLE_ABYSS_SERVER=$enable_abyss_server
+
+
+ABYSS_SUBDIR=
+LIBXMLRPC_ABYSS_SERVER_LA=
+SERVERTEST=
+VALIDATEE=
+XMLRPC_ABYSS_H=
+SERVER=
+if test x"$enable_abyss_server" != xno; then
+    FEATURE_LIST="abyss-server $FEATURE_LIST"
+    ABYSS_SUBDIR=abyss
+    LIBXMLRPC_ABYSS_SERVER_LA=libxmlrpc_abyss_server.la
+    SERVERTEST=servertest
+    VALIDATEE=validatee
+    XMLRPC_ABYSS_H=xmlrpc_abyss.h
+    SERVER=server
+fi
+
+
+
+
+
+
+
+echo "$as_me:$LINENO: checking whether to build CGI server module" >&5
+echo $ECHO_N "checking whether to build CGI server module... $ECHO_C" >&6
+# Check whether --enable-cgi-server or --disable-cgi-server was given.
+if test "${enable_cgi_server+set}" = set; then
+  enableval="$enable_cgi_server"
+  
+else
+  enable_cgi_server=yes
+fi; 
+echo "$as_me:$LINENO: result: $enable_cgi_server" >&5
+echo "${ECHO_T}$enable_cgi_server" >&6
+ENABLE_CGI_SERVER=$enable_cgi_server
+
+
+echo "$as_me:$LINENO: checking whether to build C++ wrappers and tools" >&5
+echo $ECHO_N "checking whether to build C++ wrappers and tools... $ECHO_C" >&6
+# Check whether --enable-cplusplus or --disable-cplusplus was given.
+if test "${enable_cplusplus+set}" = set; then
+  enableval="$enable_cplusplus"
+  
+else
+  enable_cplusplus=yes
+fi; 
+echo "$as_me:$LINENO: result: $enable_cplusplus" >&5
+echo "${ECHO_T}$enable_cplusplus" >&6
+ENABLE_CPLUSPLUS=$enable_cplusplus
+
+
+LIBXMLRPC_CPP_A=
+CPPTEST=
+XMLRPCCPP_H=
+XML_RPC_API2CPP_SUBDIR=
+MEERKAT_APP_LIST=
+INTEROP_CLIENT_SUBDIR=
+if test x"$enable_cplusplus" != xno; then
+    FEATURE_LIST="c++ $FEATURE_LIST"
+    LIBXMLRPC_CPP_A=libxmlrpc_cpp.a
+    CPPTEST=cpptest
+    XMLRPCCPP_H=XmlRpcCpp.h
+
+    if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+        XML_RPC_API2CPP_SUBDIR=xml-rpc-api2cpp
+    elif test $MUST_BUILD_CURL_CLIENT = yes; then
+        XML_RPC_API2CPP_SUBDIR=xml-rpc-api2cpp
+    fi
+fi
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $@%:@ != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+       ;;
+    conftest.$ac_ext )
+       # This is the source file.
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       # FIXME: I believe we export ac_cv_exeext for Libtool,
+       # but it would be cool to find out if it's true.  Does anybody
+       # maintain Libtool? --akim.
+       export ac_cv_exeext
+       break;;
+    * )
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         export ac_cv_exeext
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX                  -qlanglvl=ansi
+# Ultrix and OSF/1     -std1
+# HP-UX 10.20 and later        -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4                 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext 
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+@%:@ifndef __cplusplus
+  choke me
+@%:@endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+@%:@include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test x"$enable_cplusplus" != xno; then
+    ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+  CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+@%:@include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+
+
+
+# Code by albert chin <china@thewrittenword.com> to check for various
+# oddball networking libraries.  Solaris and some other operating systems
+# hide their networking code in various places.  (Yes, this links too many
+# of our libraries against -lsocket, but a finer-grained mechanism would
+# require too much testing.)
+echo "$as_me:$LINENO: checking for socket" >&5
+echo $ECHO_N "checking for socket... $ECHO_C" >&6
+if test "${ac_cv_func_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define socket to an innocuous variant, in case <limits.h> declares socket.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define socket innocuous_socket
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char socket (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef socket
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_socket) || defined (__stub___socket)
+choke me
+#else
+char (*f) () = socket;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != socket;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_socket=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_socket" >&5
+echo "${ECHO_T}$ac_cv_func_socket" >&6
+if test $ac_cv_func_socket = yes; then
+  :
+else
+  
+echo "$as_me:$LINENO: checking for socket in -lsocket" >&5
+echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+int
+main ()
+{
+socket ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_socket_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_socket_socket=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6
+if test $ac_cv_lib_socket_socket = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBSOCKET 1
+_ACEOF
+
+  LIBS="-lsocket $LIBS"
+
+fi
+
+fi
+
+
+# Above sets LIBS, which is not all that useful because we don't want
+# to include every library in every link.  It also sets
+# ac_cv_lib_socket_socket, which we use to pass more specific information
+# to the configuration files.
+
+if test x"$ac_cv_lib_socket_socket" = xyes; then
+  LSOCKET=-lsocket
+else
+  LSOCKET=
+fi
+
+
+# For some reason, we don't seem to need this on Solaris.  If you do
+# need it, go ahead and try it.
+# AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent))
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+@%:@ifdef __STDC__
+@%:@ include <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+@%:@include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+  
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+@%:@ifdef __STDC__
+@%:@ include <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+@%:@include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+  
+cat >>confdefs.h <<\_ACEOF
+@%:@define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+@%:@include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+fi
+
+done
+
+
+
+for ac_header in wchar.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+@%:@include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+@%:@include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+@%:@@%:@ ------------------------------------------ @%:@@%:@
+@%:@@%:@ Report this to the AC_PACKAGE_NAME lists.  @%:@@%:@
+@%:@@%:@ ------------------------------------------ @%:@@%:@
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+fi
+
+done
+
+
+if test x"$ac_cv_header_wchar_h" = xyes; then
+  HAVE_WCHAR_H_DEFINE=1
+else
+  HAVE_WCHAR_H_DEFINE=0
+fi
+
+
+# Needed by Abyss on Solaris:
+
+
+for ac_header in sys/filio.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+@%:@include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+@%:@include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+@%:@@%:@ ------------------------------------------ @%:@@%:@
+@%:@@%:@ Report this to the AC_PACKAGE_NAME lists.  @%:@@%:@
+@%:@@%:@ ------------------------------------------ @%:@@%:@
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+fi
+
+done
+
+if test x"$ac_cv_header_sys_filio_h" = xyes; then
+  HAVE_SYS_FILIO_H_DEFINE=1
+else
+  HAVE_SYS_FILIO_H_DEFINE=0
+fi
+
+
+# Needed by Abyss on Solaris:
+
+
+for ac_header in sys/ioctl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+@%:@include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+@%:@include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+@%:@@%:@ ------------------------------------------ @%:@@%:@
+@%:@@%:@ Report this to the AC_PACKAGE_NAME lists.  @%:@@%:@
+@%:@@%:@ ------------------------------------------ @%:@@%:@
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+fi
+
+done
+
+if test x"$ac_cv_header_sys_ioctl_h" = xyes; then
+  HAVE_SYS_IOCTL_H_DEFINE=1
+else
+  HAVE_SYS_IOCTL_H_DEFINE=0
+fi
+
+
+
+
+for ac_header in stdarg.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+@%:@include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+@%:@include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+@%:@@%:@ ------------------------------------------ @%:@@%:@
+@%:@@%:@ Report this to the AC_PACKAGE_NAME lists.  @%:@@%:@
+@%:@@%:@ ------------------------------------------ @%:@@%:@
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+else
+  
+{ { echo "$as_me:$LINENO: error: stdarg.h is required to build this library" >&5
+echo "$as_me: error: stdarg.h is required to build this library" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+
+done
+
+
+
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+  return 0;
+if (sizeof (size_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+  
+cat >>confdefs.h <<_ACEOF
+@%:@define size_t unsigned
+_ACEOF
+
+fi
+
+
+va_list_is_array=no
+echo "$as_me:$LINENO: checking whether va_list is an array" >&5
+echo $ECHO_N "checking whether va_list is an array... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdarg.h>
+
+int
+main ()
+{
+va_list list1, list2; list1 = list2;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+va_list_is_array=yes
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $va_list_is_array" >&5
+echo "${ECHO_T}$va_list_is_array" >&6
+if test x"$va_list_is_array" = xyes; then
+  VA_LIST_IS_ARRAY_DEFINE=1
+else
+  VA_LIST_IS_ARRAY_DEFINE=0
+fi
+
+
+echo "$as_me:$LINENO: checking whether compiler has __attribute__" >&5
+echo $ECHO_N "checking whether compiler has __attribute__... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+int x __attribute__((__unused__));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  compiler_has_attribute=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+compiler_has_attribute=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $compiler_has_attribute" >&5
+echo "${ECHO_T}$compiler_has_attribute" >&6
+if test x"$compiler_has_attribute" = xyes; then
+    ATTR_UNUSED="__attribute__((__unused__))"
+else
+    ATTR_UNUSED=
+fi
+
+
+
+
+echo "$as_me:$LINENO: checking for vsnprintf" >&5
+echo $ECHO_N "checking for vsnprintf... $ECHO_C" >&6
+if test "${ac_cv_func_vsnprintf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define vsnprintf to an innocuous variant, in case <limits.h> declares vsnprintf.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define vsnprintf innocuous_vsnprintf
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char vsnprintf (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef vsnprintf
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char vsnprintf ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_vsnprintf) || defined (__stub___vsnprintf)
+choke me
+#else
+char (*f) () = vsnprintf;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != vsnprintf;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_vsnprintf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_vsnprintf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_vsnprintf" >&5
+echo "${ECHO_T}$ac_cv_func_vsnprintf" >&6
+if test $ac_cv_func_vsnprintf = yes; then
+  :
+else
+  
+{ { echo "$as_me:$LINENO: error: your C library does not provide vsnprintf" >&5
+echo "$as_me: error: your C library does not provide vsnprintf" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+
+
+
+for ac_func in wcsncmp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+fi
+done
+
+
+
+for ac_func in setgroups
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+fi
+done
+
+
+
+for ac_func in asprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+fi
+done
+
+
+
+for ac_func in setenv
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+@%:@define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+fi
+done
+
+
+
+
+DIRECTORY_SEPARATOR="/"
+
+
+
+
+echo "$as_me:$LINENO: checking whether to use Abyss pthread function" >&5
+echo $ECHO_N "checking whether to use Abyss pthread function... $ECHO_C" >&6
+# Check whether --enable-abyss-threads or --disable-abyss-threads was given.
+if test "${enable_abyss_threads+set}" = set; then
+  enableval="$enable_abyss_threads"
+  
+else
+  enable_abyss_threads=yes
+fi; 
+echo "$as_me:$LINENO: result: $enable_abyss_threads" >&5
+echo "${ECHO_T}$enable_abyss_threads" >&6
+
+ENABLE_ABYSS_THREADS=$enable_abyss_threads
+
+
+if test x"$enable_abyss_threads" != xno; then
+    CFLAGS="$CFLAGS -D_THREAD"
+fi
+
+
+
+if test $MUST_BUILD_WININET_CLIENT = yes; then
+
+        for ac_prog in wininet-xmlrpc-config wininet-config
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_WININET_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $WININET_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_WININET_CONFIG="$WININET_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_WININET_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+WININET_CONFIG=$ac_cv_path_WININET_CONFIG
+
+if test -n "$WININET_CONFIG"; then
+  echo "$as_me:$LINENO: result: $WININET_CONFIG" >&5
+echo "${ECHO_T}$WININET_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$WININET_CONFIG" && break
+done
+test -n "$WININET_CONFIG" || WININET_CONFIG="no"
+
+    if test "x$WININET_CONFIG" = "xno"; then
+        { { echo "$as_me:$LINENO: error: wininet lib not found; see './configure --help'" >&5
+echo "$as_me: error: wininet lib not found; see './configure --help'" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+            echo "$as_me:$LINENO: checking for wininet version >= 1.0.0" >&5
+echo $ECHO_N "checking for wininet version >= 1.0.0... $ECHO_C" >&6
+    W3VER=`$WININET_CONFIG --version`
+    WININET_MAJOR=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+    WININET_MINOR=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+    WININET_MICRO=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+    echo "$as_me:$LINENO: result: $WININET_MAJOR.$WININET_MINOR.$WININET_MICRO" >&5
+echo "${ECHO_T}$WININET_MAJOR.$WININET_MINOR.$WININET_MICRO" >&6
+
+        WININET_VERSION_OK=yes
+    if test $WININET_MAJOR -lt 1; then
+        WININET_VERSION_OK=no
+    else
+        if test $WININET_MAJOR -eq 1 -a $WININET_MINOR -lt 0; then
+            WININET_VERSION_OK=no
+        else
+            if test $WININET_MAJOR -eq 1 -a $WININET_MINOR -eq 0 \
+                -a $WININET_MICRO -lt 0; then
+                WININET_VERSION_OK=no
+            fi
+        fi
+    fi
+    if test "x$WININET_VERSION_OK" = "xno"; then
+        { { echo "$as_me:$LINENO: error: wininet version >= 1.0.0 required" >&5
+echo "$as_me: error: wininet version >= 1.0.0 required" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+        WININET_CFLAGS="`$WININET_CONFIG --cflags`"
+    
+    CFLAGS="$CFLAGS $WININET_CFLAGS" 
+
+        WININET_LDADD="`$WININET_CONFIG --libs`"
+    
+
+                echo "$as_me:$LINENO: checking for wininet library directory" >&5
+echo $ECHO_N "checking for wininet library directory... $ECHO_C" >&6
+    if $WININET_CONFIG --rpath-dir > /dev/null 2>&1; then
+              WININET_LIBDIR="`$WININET_CONFIG --rpath-dir`"
+    else
+              WININET_LIBDIR="`$WININET_CONFIG --prefix`/lib"
+    fi
+    echo "$as_me:$LINENO: result: $WININET_LIBDIR" >&5
+echo "${ECHO_T}$WININET_LIBDIR" >&6
+    
+    WININET_RPATH="-rpath $WININET_LIBDIR"
+    
+    WININET_WL_RPATH="-Wl,--rpath -Wl,$WININET_LIBDIR"
+    
+
+fi # MUST_BUILD_WININET_CLIENT
+
+
+if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+
+            for ac_prog in libwww-xmlrpc-config libwww-config
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_LIBWWW_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $LIBWWW_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LIBWWW_CONFIG="$LIBWWW_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LIBWWW_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+LIBWWW_CONFIG=$ac_cv_path_LIBWWW_CONFIG
+
+if test -n "$LIBWWW_CONFIG"; then
+  echo "$as_me:$LINENO: result: $LIBWWW_CONFIG" >&5
+echo "${ECHO_T}$LIBWWW_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$LIBWWW_CONFIG" && break
+done
+test -n "$LIBWWW_CONFIG" || LIBWWW_CONFIG="no"
+
+    if test "x$LIBWWW_CONFIG" = "xno"; then
+        { { echo "$as_me:$LINENO: error: w3c-libwww not found; see './configure --help'" >&5
+echo "$as_me: error: w3c-libwww not found; see './configure --help'" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+            echo "$as_me:$LINENO: checking for w3c-libwww version >= 5.2.8" >&5
+echo $ECHO_N "checking for w3c-libwww version >= 5.2.8... $ECHO_C" >&6
+    W3VER=`$LIBWWW_CONFIG --version`
+    LIBWWW_MAJOR=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+    LIBWWW_MINOR=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+    LIBWWW_MICRO=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+    echo "$as_me:$LINENO: result: $LIBWWW_MAJOR.$LIBWWW_MINOR.$LIBWWW_MICRO" >&5
+echo "${ECHO_T}$LIBWWW_MAJOR.$LIBWWW_MINOR.$LIBWWW_MICRO" >&6
+
+        LIBWWW_VERSION_OK=yes
+    if test $LIBWWW_MAJOR -lt 5; then
+        LIBWWW_VERSION_OK=no
+    else
+        if test $LIBWWW_MAJOR -eq 5 -a $LIBWWW_MINOR -lt 2; then
+            LIBWWW_VERSION_OK=no
+        else
+            if test $LIBWWW_MAJOR -eq 5 -a $LIBWWW_MINOR -eq 2 \
+                -a $LIBWWW_MICRO -lt 8; then
+                LIBWWW_VERSION_OK=no
+            fi
+        fi
+    fi
+    if test "x$LIBWWW_VERSION_OK" = "xno"; then
+        { { echo "$as_me:$LINENO: error: w3c-libwww version >= 5.2.8 required" >&5
+echo "$as_me: error: w3c-libwww version >= 5.2.8 required" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+        LIBWWW_LDADD="`$LIBWWW_CONFIG --libs`"
+    
+
+                echo "$as_me:$LINENO: checking for libwww library directory" >&5
+echo $ECHO_N "checking for libwww library directory... $ECHO_C" >&6
+    if $LIBWWW_CONFIG --rpath-dir > /dev/null 2>&1; then
+              LIBWWW_LIBDIR="`$LIBWWW_CONFIG --rpath-dir`"
+    else
+              LIBWWW_LIBDIR="`$LIBWWW_CONFIG --prefix`/lib"
+    fi
+    echo "$as_me:$LINENO: result: $LIBWWW_LIBDIR" >&5
+echo "${ECHO_T}$LIBWWW_LIBDIR" >&6
+    
+
+    # Some ancient rpath stuff, now disabled.  I turned this off because it
+    # breaks Debian (and Mandrake?) policy, and we don't use it anymore.
+    # If you have multiple copies of w3c-libwww lying around, you can turn
+    # it back on.
+    #LIBWWW_RPATH="-rpath $LIBWWW_LIBDIR"
+    LIBWWW_RPATH=""
+    
+    #LIBWWW_WL_RPATH="-Wl,--rpath -Wl,$LIBWWW_LIBDIR"
+    LIBWWW_WL_RPATH=""
+    
+
+fi # MUST_BUILD_LIBWWW_CLIENT
+
+
+
+if test $MUST_BUILD_CURL_CLIENT = yes; then
+
+            for ac_prog in curl-xmlrpc-config curl-config
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_CURL_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $CURL_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_CURL_CONFIG="$CURL_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_CURL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+CURL_CONFIG=$ac_cv_path_CURL_CONFIG
+
+if test -n "$CURL_CONFIG"; then
+  echo "$as_me:$LINENO: result: $CURL_CONFIG" >&5
+echo "${ECHO_T}$CURL_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$CURL_CONFIG" && break
+done
+test -n "$CURL_CONFIG" || CURL_CONFIG="no"
+
+    if test "x$CURL_CONFIG" = "xno"; then
+        { { echo "$as_me:$LINENO: error: cURL not found; see './configure --help'" >&5
+echo "$as_me: error: cURL not found; see './configure --help'" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+    
+                            
+                    CURL_LDADD=`$CURL_CONFIG --libs`
+    
+
+                echo "$as_me:$LINENO: checking for curl library directory" >&5
+echo $ECHO_N "checking for curl library directory... $ECHO_C" >&6
+        CURL_LIBDIR="`$CURL_CONFIG --prefix`/lib"
+
+    echo "$as_me:$LINENO: result: $CURL_LIBDIR" >&5
+echo "${ECHO_T}$CURL_LIBDIR" >&6
+    
+    CURL_RPATH="-rpath $CURL_LIBDIR"
+    
+    CURL_WL_RPATH="-Wl,--rpath -Wl,$CURL_LIBDIR"
+    
+
+fi # MUST_BUILD_CURL_CLIENT
+
+
+
+
+# Check whether --with-libwww-ssl or --without-libwww-ssl was given.
+if test "${with_libwww_ssl+set}" = set; then
+  withval="$with_libwww_ssl"
+  
+fi;  
+
+if test x"$enable_libwww_client" != xno; then
+    echo "$as_me:$LINENO: checking whether to use SSL with libwww" >&5
+echo $ECHO_N "checking whether to use SSL with libwww... $ECHO_C" >&6
+    if test x"$with_libwww_ssl" = xyes; then
+        echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+        HAVE_LIBWWW_SSL_DEFINE=1
+    else
+        echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+        HAVE_LIBWWW_SSL_DEFINE=0
+    fi
+fi
+
+
+# Check whether --enable-libxml2-backend or --disable-libxml2-backend was given.
+if test "${enable_libxml2_backend+set}" = set; then
+  enableval="$enable_libxml2_backend"
+  
+else
+  enable_libxml2_backend=no
+fi; 
+echo "$as_me:$LINENO: checking whether to build the libxml2 backend" >&5
+echo $ECHO_N "checking whether to build the libxml2 backend... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $enable_libxml2_backend" >&5
+echo "${ECHO_T}$enable_libxml2_backend" >&6
+
+if test $enable_libxml2_backend = yes; then
+  # Extract the first word of "xml2-config", so it can be a program name with args.
+set dummy xml2-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_have_xml2_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$have_xml2_config"; then
+  ac_cv_prog_have_xml2_config="$have_xml2_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_xml2_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_have_xml2_config" && ac_cv_prog_have_xml2_config="no"
+fi
+fi
+have_xml2_config=$ac_cv_prog_have_xml2_config
+if test -n "$have_xml2_config"; then
+  echo "$as_me:$LINENO: result: $have_xml2_config" >&5
+echo "${ECHO_T}$have_xml2_config" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  if test $have_xml2_config = no; then
+    { { echo "$as_me:$LINENO: error: You specified --enable-libxml2_backend, but don't appear to have libxml2 installed (no working xml2-config inyour command search path), so we cannot not build for libxml2" >&5
+echo "$as_me: error: You specified --enable-libxml2_backend, but don't appear to have libxml2 installed (no working xml2-config inyour command search path), so we cannot not build for libxml2" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+ENABLE_LIBXML2_BACKEND=$enable_libxml2_backend
+
+
+C_COMPILER_GNU=$ac_cv_c_compiler_gnu
+
+CXX_COMPILER_GNU=$ac_cv_cxx_compiler_gnu
+
+
+CC_WARN_FLAGS=
+
+CPP_WARN_FLAGS=
+
+
+
+BUILDDIR=`pwd`
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval="$enable_shared"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_shared=yes
+fi; 
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval="$enable_static"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_static=yes
+fi; 
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval="$enable_fast_install"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_fast_install=yes
+fi; 
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi; 
+ac_prog=ld
+if test "$ac_cv_c_compiler_gnu" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6
+  ac_prog=`($CC -print-prog-name=ld) 2>&5`
+  case "$ac_prog" in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${ac_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      ac_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+  echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${ac_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  ac_cv_prog_gnu_ld=yes
+else
+  ac_cv_prog_gnu_ld=no
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$ac_cv_prog_gnu_ld" >&6
+
+
+echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
+if test "${ac_cv_path_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  ac_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -B"
+       break
+      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -p"
+       break
+      else
+       ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi
+fi
+
+NM="$ac_cv_path_NM"
+echo "$as_me:$LINENO: result: $NM" >&5
+echo "${ECHO_T}$NM" >&6
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+
+case "$target" in
+NONE) lt_target="$host" ;;
+*) lt_target="$target" ;;
+esac
+
+# Check for any special flags to pass to ltconfig.
+#
+# the following will cause an existing older ltconfig to fail, so
+# we ignore this at the expense of the cache file... Checking this 
+# will just take longer ... bummer!
+#libtool_flags="--cache-file=$cache_file"
+#
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$ac_cv_c_compiler_gnu" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval="$enable_libtool_lock"
+  
+fi; 
+test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
+test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$lt_target" in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line __oline__ "configure"' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  lt_cv_cc_needs_belf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+lt_cv_cc_needs_belf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+
+esac
+
+
+# Save cache, so that ltconfig can load it
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
+LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
+DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \
+|| { { echo "$as_me:$LINENO: error: libtool configure failed" >&5
+echo "$as_me: error: libtool configure failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+# Reload cache, that may have been modified by ltconfig
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+
+
+
+
+
+                                        ac_config_files="$ac_config_files xmlrpc-c-config xmlrpc-c-config.test Makefile.config xmlrpc_config.h"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[    ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[      ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIB@&t@OBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIB@&t@OBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../@%:@@%:@ /;s/...$/ @%:@@%:@/;p;x;p;x' <<_ASBOX
+@%:@@%:@ Running $as_me. @%:@@%:@
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                  instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                  instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "xmlrpc-c-config" ) CONFIG_FILES="$CONFIG_FILES xmlrpc-c-config" ;;
+  "xmlrpc-c-config.test" ) CONFIG_FILES="$CONFIG_FILES xmlrpc-c-config.test" ;;
+  "Makefile.config" ) CONFIG_FILES="$CONFIG_FILES Makefile.config" ;;
+  "xmlrpc_config.h" ) CONFIG_FILES="$CONFIG_FILES xmlrpc_config.h" ;;
+  "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+  "xmlrpc_amconfig.h" ) CONFIG_HEADERS="$CONFIG_HEADERS xmlrpc_amconfig.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOMAKE@,$AUTOMAKE,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@VERSION_INFO@,$VERSION_INFO,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@have_wininet_config@,$have_wininet_config,;t t
+s,@MUST_BUILD_WININET_CLIENT@,$MUST_BUILD_WININET_CLIENT,;t t
+s,@have_curl_config@,$have_curl_config,;t t
+s,@MUST_BUILD_CURL_CLIENT@,$MUST_BUILD_CURL_CLIENT,;t t
+s,@have_libwww_config@,$have_libwww_config,;t t
+s,@MUST_BUILD_LIBWWW_CLIENT@,$MUST_BUILD_LIBWWW_CLIENT,;t t
+s,@LIBXMLRPC_CLIENT_LA@,$LIBXMLRPC_CLIENT_LA,;t t
+s,@CLIENTTEST@,$CLIENTTEST,;t t
+s,@XMLRPC_CLIENT_H@,$XMLRPC_CLIENT_H,;t t
+s,@XMLRPC_TRANSPORT_H@,$XMLRPC_TRANSPORT_H,;t t
+s,@SYNCH_CLIENT@,$SYNCH_CLIENT,;t t
+s,@ASYNCH_CLIENT@,$ASYNCH_CLIENT,;t t
+s,@AUTH_CLIENT@,$AUTH_CLIENT,;t t
+s,@QUERY_MEERKAT@,$QUERY_MEERKAT,;t t
+s,@ENABLE_ABYSS_SERVER@,$ENABLE_ABYSS_SERVER,;t t
+s,@ABYSS_SUBDIR@,$ABYSS_SUBDIR,;t t
+s,@LIBXMLRPC_ABYSS_SERVER_LA@,$LIBXMLRPC_ABYSS_SERVER_LA,;t t
+s,@SERVERTEST@,$SERVERTEST,;t t
+s,@VALIDATEE@,$VALIDATEE,;t t
+s,@XMLRPC_ABYSS_H@,$XMLRPC_ABYSS_H,;t t
+s,@SERVER@,$SERVER,;t t
+s,@ENABLE_CGI_SERVER@,$ENABLE_CGI_SERVER,;t t
+s,@ENABLE_CPLUSPLUS@,$ENABLE_CPLUSPLUS,;t t
+s,@LIBXMLRPC_CPP_A@,$LIBXMLRPC_CPP_A,;t t
+s,@CPPTEST@,$CPPTEST,;t t
+s,@XMLRPCCPP_H@,$XMLRPCCPP_H,;t t
+s,@XML_RPC_API2CPP_SUBDIR@,$XML_RPC_API2CPP_SUBDIR,;t t
+s,@FEATURE_LIST@,$FEATURE_LIST,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@LSOCKET@,$LSOCKET,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@HAVE_WCHAR_H_DEFINE@,$HAVE_WCHAR_H_DEFINE,;t t
+s,@HAVE_SYS_FILIO_H_DEFINE@,$HAVE_SYS_FILIO_H_DEFINE,;t t
+s,@HAVE_SYS_IOCTL_H_DEFINE@,$HAVE_SYS_IOCTL_H_DEFINE,;t t
+s,@VA_LIST_IS_ARRAY_DEFINE@,$VA_LIST_IS_ARRAY_DEFINE,;t t
+s,@ATTR_UNUSED@,$ATTR_UNUSED,;t t
+s,@DIRECTORY_SEPARATOR@,$DIRECTORY_SEPARATOR,;t t
+s,@ENABLE_ABYSS_THREADS@,$ENABLE_ABYSS_THREADS,;t t
+s,@WININET_CONFIG@,$WININET_CONFIG,;t t
+s,@WININET_CFLAGS@,$WININET_CFLAGS,;t t
+s,@WININET_LDADD@,$WININET_LDADD,;t t
+s,@WININET_LIBDIR@,$WININET_LIBDIR,;t t
+s,@WININET_RPATH@,$WININET_RPATH,;t t
+s,@WININET_WL_RPATH@,$WININET_WL_RPATH,;t t
+s,@LIBWWW_CONFIG@,$LIBWWW_CONFIG,;t t
+s,@LIBWWW_LDADD@,$LIBWWW_LDADD,;t t
+s,@LIBWWW_LIBDIR@,$LIBWWW_LIBDIR,;t t
+s,@LIBWWW_RPATH@,$LIBWWW_RPATH,;t t
+s,@LIBWWW_WL_RPATH@,$LIBWWW_WL_RPATH,;t t
+s,@CURL_CONFIG@,$CURL_CONFIG,;t t
+s,@CURL_LDADD@,$CURL_LDADD,;t t
+s,@CURL_LIBDIR@,$CURL_LIBDIR,;t t
+s,@CURL_RPATH@,$CURL_RPATH,;t t
+s,@CURL_WL_RPATH@,$CURL_WL_RPATH,;t t
+s,@HAVE_LIBWWW_SSL_DEFINE@,$HAVE_LIBWWW_SSL_DEFINE,;t t
+s,@have_xml2_config@,$have_xml2_config,;t t
+s,@ENABLE_LIBXML2_BACKEND@,$ENABLE_LIBXML2_BACKEND,;t t
+s,@C_COMPILER_GNU@,$C_COMPILER_GNU,;t t
+s,@CXX_COMPILER_GNU@,$CXX_COMPILER_GNU,;t t
+s,@CC_WARN_FLAGS@,$CC_WARN_FLAGS,;t t
+s,@CPP_WARN_FLAGS@,$CPP_WARN_FLAGS,;t t
+s,@BUILDDIR@,$BUILDDIR,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@LN_S@,$LN_S,;t t
+s,@LIBTOOL@,$LIBTOOL,;t t
+s,@LIB@&t@OBJS@,$LIB@&t@OBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                    sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([   ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='[        ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([   ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        # Do quote $f, to prevent DOS paths from being IFS'd.
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[      ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*\)\(([^)]*)\)[       ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[    ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[     ]*#[    ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[     ]*#[    ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[     ]*#[    ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+  ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_dest" : 'X\(//\)[^/]' \| \
+        X"$ac_dest" : 'X\(//\)$' \| \
+        X"$ac_dest" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+  case $ac_dest in
+    default-1 ) test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h ;;
+  esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+chmod +x xmlrpc-c-config
+chmod +x xmlrpc-c-config.test
diff --git a/autom4te.cache/requests b/autom4te.cache/requests
new file mode 100644 (file)
index 0000000..37b7fbc
--- /dev/null
@@ -0,0 +1,225 @@
+# This file was generated.
+# It contains the lists of macros which have been traced.
+# It can be safely removed.
+
+@request = (
+             bless( [
+                      '0',
+                      1,
+                      [
+                        '/subsys/autoconf/share'
+                      ],
+                      [
+                        '/subsys/autoconf/share/autoconf/autoconf.m4f',
+                        'aclocal.m4',
+                        'configure.in'
+                      ],
+                      {
+                        'AC_CANONICAL_SYSTEM' => 1,
+                        'AC_HEADER_STAT' => 1,
+                        'AC_FUNC_STRFTIME' => 1,
+                        'AC_PROG_RANLIB' => 1,
+                        'AC_C_VOLATILE' => 1,
+                        'AC_FUNC_WAIT3' => 1,
+                        'AC_CONFIG_AUX_DIR' => 1,
+                        'AC_REPLACE_FNMATCH' => 1,
+                        'AC_FUNC_SETPGRP' => 1,
+                        'AC_HEADER_TIME' => 1,
+                        'AC_FUNC_SETVBUF_REVERSED' => 1,
+                        'AC_HEADER_SYS_WAIT' => 1,
+                        'AC_TYPE_UID_T' => 1,
+                        'AM_CONDITIONAL' => 1,
+                        'AC_CHECK_LIB' => 1,
+                        'AC_PROG_LN_S' => 1,
+                        'AC_FUNC_MEMCMP' => 1,
+                        'AM_PROG_CC_C_O' => 1,
+                        'AC_CONFIG_LIBOBJ_DIR' => 1,
+                        'AC_FUNC_FORK' => 1,
+                        'AC_FUNC_GETGROUPS' => 1,
+                        'AC_HEADER_MAJOR' => 1,
+                        'AC_FUNC_STRNLEN' => 1,
+                        'AC_FUNC_STRTOD' => 1,
+                        'AC_HEADER_DIRENT' => 1,
+                        'AC_FUNC_UTIME_NULL' => 1,
+                        'AC_FUNC_MBRTOWC' => 1,
+                        '_m4_warn' => 1,
+                        'AC_CONFIG_FILES' => 1,
+                        'AC_FUNC_ALLOCA' => 1,
+                        'AC_C_CONST' => 1,
+                        'AC_CHECK_MEMBERS' => 1,
+                        'AC_FUNC_REALLOC' => 1,
+                        'include' => 1,
+                        'AC_FUNC_OBSTACK' => 1,
+                        'AC_FUNC_LSTAT' => 1,
+                        'AC_STRUCT_TIMEZONE' => 1,
+                        'AC_FUNC_GETPGRP' => 1,
+                        'AC_DEFINE_TRACE_LITERAL' => 1,
+                        'AC_CHECK_HEADERS' => 1,
+                        'AC_TYPE_MODE_T' => 1,
+                        'AC_CHECK_TYPES' => 1,
+                        'AC_PROG_YACC' => 1,
+                        'AC_TYPE_PID_T' => 1,
+                        'AC_FUNC_STRERROR_R' => 1,
+                        'AM_AUTOMAKE_VERSION' => 1,
+                        'AC_STRUCT_ST_BLOCKS' => 1,
+                        'AC_FUNC_SELECT_ARGTYPES' => 1,
+                        'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
+                        'AC_TYPE_SIGNAL' => 1,
+                        'AC_PROG_GCC_TRADITIONAL' => 1,
+                        'm4_sinclude' => 1,
+                        'AC_PROG_CPP' => 1,
+                        'AC_FUNC_STAT' => 1,
+                        'AC_PROG_INSTALL' => 1,
+                        'sinclude' => 1,
+                        'AC_CONFIG_SUBDIRS' => 1,
+                        'AM_GNU_GETTEXT' => 1,
+                        'AC_FUNC_STRCOLL' => 1,
+                        'AC_LIBSOURCE' => 1,
+                        'AC_C_INLINE' => 1,
+                        'AC_FUNC_CHOWN' => 1,
+                        'AC_FUNC_GETMNTENT' => 1,
+                        'AC_INIT' => 1,
+                        'AC_PROG_LEX' => 1,
+                        'AH_OUTPUT' => 1,
+                        'AC_HEADER_STDC' => 1,
+                        'AC_FUNC_GETLOADAVG' => 1,
+                        'AC_TYPE_SIZE_T' => 1,
+                        'AC_CHECK_FUNCS' => 1,
+                        'AC_DECL_SYS_SIGLIST' => 1,
+                        'AC_FUNC_MKTIME' => 1,
+                        'AC_PROG_MAKE_SET' => 1,
+                        'AC_CONFIG_LINKS' => 1,
+                        'AC_PROG_CXX' => 1,
+                        'AC_CANONICAL_HOST' => 1,
+                        'AC_FUNC_CLOSEDIR_VOID' => 1,
+                        'm4_pattern_allow' => 1,
+                        'm4_include' => 1,
+                        'm4_pattern_forbid' => 1,
+                        'AC_PROG_AWK' => 1,
+                        'AC_FUNC_VPRINTF' => 1,
+                        'AC_CONFIG_HEADERS' => 1,
+                        'AC_TYPE_OFF_T' => 1,
+                        'AC_PATH_X' => 1,
+                        'AC_FUNC_MALLOC' => 1,
+                        'AM_MAINTAINER_MODE' => 1,
+                        'AC_FUNC_ERROR_AT_LINE' => 1,
+                        'AC_FUNC_FSEEKO' => 1,
+                        'AC_STRUCT_TM' => 1,
+                        'AC_FUNC_MMAP' => 1,
+                        'AM_INIT_AUTOMAKE' => 1,
+                        'AC_SUBST' => 1,
+                        'AC_PROG_LIBTOOL' => 1,
+                        'AC_PROG_CC' => 1
+                      }
+                    ], 'Autom4te::Request' ),
+             bless( [
+                      '1',
+                      1,
+                      [
+                        '/subsys2/autoconf/share'
+                      ],
+                      [
+                        '/subsys2/autoconf/share/autoconf/autoconf.m4f',
+                        'aclocal.m4',
+                        'configure.in'
+                      ],
+                      {
+                        'AC_CANONICAL_SYSTEM' => 1,
+                        'AC_HEADER_STAT' => 1,
+                        'AC_FUNC_STRFTIME' => 1,
+                        'AC_PROG_RANLIB' => 1,
+                        'AC_C_VOLATILE' => 1,
+                        'AC_FUNC_WAIT3' => 1,
+                        'AC_CONFIG_AUX_DIR' => 1,
+                        'AC_REPLACE_FNMATCH' => 1,
+                        'AC_FUNC_SETPGRP' => 1,
+                        'AC_HEADER_TIME' => 1,
+                        'AC_FUNC_SETVBUF_REVERSED' => 1,
+                        'AC_HEADER_SYS_WAIT' => 1,
+                        'AC_TYPE_UID_T' => 1,
+                        'AM_CONDITIONAL' => 1,
+                        'AC_CHECK_LIB' => 1,
+                        'AC_PROG_LN_S' => 1,
+                        'AC_FUNC_MEMCMP' => 1,
+                        'AM_PROG_CC_C_O' => 1,
+                        'AC_CONFIG_LIBOBJ_DIR' => 1,
+                        'AC_FUNC_FORK' => 1,
+                        'AC_FUNC_GETGROUPS' => 1,
+                        'AC_HEADER_MAJOR' => 1,
+                        'AC_FUNC_STRNLEN' => 1,
+                        'AC_FUNC_STRTOD' => 1,
+                        'AC_HEADER_DIRENT' => 1,
+                        'AC_FUNC_UTIME_NULL' => 1,
+                        'AC_FUNC_MBRTOWC' => 1,
+                        '_m4_warn' => 1,
+                        'AC_CONFIG_FILES' => 1,
+                        'AC_FUNC_ALLOCA' => 1,
+                        'AC_C_CONST' => 1,
+                        'AC_CHECK_MEMBERS' => 1,
+                        'AC_FUNC_REALLOC' => 1,
+                        'include' => 1,
+                        'AC_FUNC_OBSTACK' => 1,
+                        'AC_FUNC_LSTAT' => 1,
+                        'AC_STRUCT_TIMEZONE' => 1,
+                        'AC_FUNC_GETPGRP' => 1,
+                        'AC_DEFINE_TRACE_LITERAL' => 1,
+                        'AC_CHECK_HEADERS' => 1,
+                        'AC_TYPE_MODE_T' => 1,
+                        'AC_CHECK_TYPES' => 1,
+                        'AC_PROG_YACC' => 1,
+                        'AC_TYPE_PID_T' => 1,
+                        'AC_FUNC_STRERROR_R' => 1,
+                        'AM_AUTOMAKE_VERSION' => 1,
+                        'AC_STRUCT_ST_BLOCKS' => 1,
+                        'AC_FUNC_SELECT_ARGTYPES' => 1,
+                        'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
+                        'AC_TYPE_SIGNAL' => 1,
+                        'AC_PROG_GCC_TRADITIONAL' => 1,
+                        'm4_sinclude' => 1,
+                        'AC_PROG_CPP' => 1,
+                        'AC_FUNC_STAT' => 1,
+                        'AC_PROG_INSTALL' => 1,
+                        'sinclude' => 1,
+                        'AC_CONFIG_SUBDIRS' => 1,
+                        'AM_GNU_GETTEXT' => 1,
+                        'AC_FUNC_STRCOLL' => 1,
+                        'AC_LIBSOURCE' => 1,
+                        'AC_C_INLINE' => 1,
+                        'AC_FUNC_CHOWN' => 1,
+                        'AC_FUNC_GETMNTENT' => 1,
+                        'AC_INIT' => 1,
+                        'AC_PROG_LEX' => 1,
+                        'AH_OUTPUT' => 1,
+                        'AC_HEADER_STDC' => 1,
+                        'AC_FUNC_GETLOADAVG' => 1,
+                        'AC_TYPE_SIZE_T' => 1,
+                        'AC_CHECK_FUNCS' => 1,
+                        'AC_DECL_SYS_SIGLIST' => 1,
+                        'AC_FUNC_MKTIME' => 1,
+                        'AC_PROG_MAKE_SET' => 1,
+                        'AC_CONFIG_LINKS' => 1,
+                        'AC_PROG_CXX' => 1,
+                        'AC_CANONICAL_HOST' => 1,
+                        'AC_FUNC_CLOSEDIR_VOID' => 1,
+                        'm4_pattern_allow' => 1,
+                        'm4_include' => 1,
+                        'm4_pattern_forbid' => 1,
+                        'AC_PROG_AWK' => 1,
+                        'AC_FUNC_VPRINTF' => 1,
+                        'AC_CONFIG_HEADERS' => 1,
+                        'AC_TYPE_OFF_T' => 1,
+                        'AC_PATH_X' => 1,
+                        'AC_FUNC_MALLOC' => 1,
+                        'AM_MAINTAINER_MODE' => 1,
+                        'AC_FUNC_ERROR_AT_LINE' => 1,
+                        'AC_FUNC_FSEEKO' => 1,
+                        'AC_STRUCT_TM' => 1,
+                        'AC_FUNC_MMAP' => 1,
+                        'AM_INIT_AUTOMAKE' => 1,
+                        'AC_SUBST' => 1,
+                        'AC_PROG_LIBTOOL' => 1,
+                        'AC_PROG_CC' => 1
+                      }
+                    ], 'Autom4te::Request' )
+           );
+
diff --git a/autom4te.cache/traces.0 b/autom4te.cache/traces.0
new file mode 100644 (file)
index 0000000..38d5970
--- /dev/null
@@ -0,0 +1,286 @@
+m4trace:configure.in:3: -1- AC_INIT([include/xmlrpc-c/base.h])
+m4trace:configure.in:3: -1- m4_pattern_forbid([^_?A[CHUM]_])
+m4trace:configure.in:3: -1- m4_pattern_forbid([_AC_])
+m4trace:configure.in:3: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS'])
+m4trace:configure.in:3: -1- m4_pattern_allow([^AS_FLAGS$])
+m4trace:configure.in:3: -1- m4_pattern_forbid([^_?m4_])
+m4trace:configure.in:3: -1- m4_pattern_forbid([^dnl$])
+m4trace:configure.in:3: -1- m4_pattern_forbid([^_?AS_])
+m4trace:configure.in:3: -1- AC_SUBST([SHELL], [${CONFIG_SHELL-/bin/sh}])
+m4trace:configure.in:3: -1- AC_SUBST([PATH_SEPARATOR])
+m4trace:configure.in:3: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME],      ['AC_PACKAGE_NAME'])])
+m4trace:configure.in:3: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME],   ['AC_PACKAGE_TARNAME'])])
+m4trace:configure.in:3: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION],   ['AC_PACKAGE_VERSION'])])
+m4trace:configure.in:3: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING],    ['AC_PACKAGE_STRING'])])
+m4trace:configure.in:3: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])])
+m4trace:configure.in:3: -1- AC_SUBST([exec_prefix], [NONE])
+m4trace:configure.in:3: -1- AC_SUBST([prefix], [NONE])
+m4trace:configure.in:3: -1- AC_SUBST([program_transform_name], [s,x,x,])
+m4trace:configure.in:3: -1- AC_SUBST([bindir], ['${exec_prefix}/bin'])
+m4trace:configure.in:3: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin'])
+m4trace:configure.in:3: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec'])
+m4trace:configure.in:3: -1- AC_SUBST([datadir], ['${prefix}/share'])
+m4trace:configure.in:3: -1- AC_SUBST([sysconfdir], ['${prefix}/etc'])
+m4trace:configure.in:3: -1- AC_SUBST([sharedstatedir], ['${prefix}/com'])
+m4trace:configure.in:3: -1- AC_SUBST([localstatedir], ['${prefix}/var'])
+m4trace:configure.in:3: -1- AC_SUBST([libdir], ['${exec_prefix}/lib'])
+m4trace:configure.in:3: -1- AC_SUBST([includedir], ['${prefix}/include'])
+m4trace:configure.in:3: -1- AC_SUBST([oldincludedir], ['/usr/include'])
+m4trace:configure.in:3: -1- AC_SUBST([infodir], ['${prefix}/info'])
+m4trace:configure.in:3: -1- AC_SUBST([mandir], ['${prefix}/man'])
+m4trace:configure.in:3: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME])
+m4trace:configure.in:3: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */
+#undef PACKAGE_NAME])
+m4trace:configure.in:3: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME])
+m4trace:configure.in:3: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME])
+m4trace:configure.in:3: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION])
+m4trace:configure.in:3: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */
+#undef PACKAGE_VERSION])
+m4trace:configure.in:3: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING])
+m4trace:configure.in:3: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING])
+m4trace:configure.in:3: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT])
+m4trace:configure.in:3: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT])
+m4trace:configure.in:3: -1- AC_SUBST([build_alias])
+m4trace:configure.in:3: -1- AC_SUBST([host_alias])
+m4trace:configure.in:3: -1- AC_SUBST([target_alias])
+m4trace:configure.in:3: -1- AC_SUBST([DEFS])
+m4trace:configure.in:3: -1- AC_SUBST([ECHO_C])
+m4trace:configure.in:3: -1- AC_SUBST([ECHO_N])
+m4trace:configure.in:3: -1- AC_SUBST([ECHO_T])
+m4trace:configure.in:3: -1- AC_SUBST([LIBS])
+m4trace:configure.in:4: -1- AC_CONFIG_HEADERS([xmlrpc_amconfig.h])
+m4trace:configure.in:4: -1- _m4_warn([obsolete], [The macro `AC_OUTPUT_COMMANDS' is obsolete.
+You should run autoupdate.], [autoconf/status.m4:318: AC_OUTPUT_COMMANDS is expanded from...
+aclocal.m4:34: AM_CONFIG_HEADER is expanded from...
+configure.in:4: the top level])
+m4trace:configure.in:4: -3- _m4_warn([obsolete], [The macro `_AC_OUTPUT_COMMANDS_CNT' is obsolete.
+You should run autoupdate.], [autoconf/status.m4:321: _AC_OUTPUT_COMMANDS_CNT is expanded from...
+autoconf/status.m4:318: AC_OUTPUT_COMMANDS is expanded from...
+aclocal.m4:34: AM_CONFIG_HEADER is expanded from...
+configure.in:4: the top level])
+m4trace:configure.in:11: -1- AM_INIT_AUTOMAKE([xmlrpc-c], [1.06.31])
+m4trace:configure.in:11: -1- AC_PROG_INSTALL
+m4trace:configure.in:11: -1- AC_SUBST([INSTALL_PROGRAM])
+m4trace:configure.in:11: -1- AC_SUBST([INSTALL_SCRIPT])
+m4trace:configure.in:11: -1- AC_SUBST([INSTALL_DATA])
+m4trace:configure.in:11: -1- AC_SUBST([PACKAGE])
+m4trace:configure.in:11: -1- AC_SUBST([VERSION])
+m4trace:configure.in:11: -2- AC_DEFINE_TRACE_LITERAL([PACKAGE])
+m4trace:configure.in:11: -2- AH_OUTPUT([PACKAGE], [/* Name of package */
+#undef PACKAGE])
+m4trace:configure.in:11: -2- AC_DEFINE_TRACE_LITERAL([VERSION])
+m4trace:configure.in:11: -2- AH_OUTPUT([VERSION], [/* Version number of package */
+#undef VERSION])
+m4trace:configure.in:11: -1- AC_SUBST([ACLOCAL])
+m4trace:configure.in:11: -1- AC_SUBST([AUTOCONF])
+m4trace:configure.in:11: -1- AC_SUBST([AUTOMAKE])
+m4trace:configure.in:11: -1- AC_SUBST([AUTOHEADER])
+m4trace:configure.in:11: -1- AC_SUBST([MAKEINFO])
+m4trace:configure.in:11: -1- AC_PROG_MAKE_SET
+m4trace:configure.in:11: -1- AC_SUBST([SET_MAKE])
+m4trace:configure.in:17: -1- AC_SUBST([VERSION_INFO])
+m4trace:configure.in:23: -1- AC_CANONICAL_HOST
+m4trace:configure.in:23: -1- AC_SUBST([build], [$ac_cv_build])
+m4trace:configure.in:23: -1- AC_SUBST([build_cpu], [`echo $ac_cv_build | sed 's/^\([[^-]]*\)-\([[^-]]*\)-\(.*\)$/\1/'`])
+m4trace:configure.in:23: -1- AC_SUBST([build_vendor], [`echo $ac_cv_build | sed 's/^\([[^-]]*\)-\([[^-]]*\)-\(.*\)$/\2/'`])
+m4trace:configure.in:23: -1- AC_SUBST([build_os], [`echo $ac_cv_build | sed 's/^\([[^-]]*\)-\([[^-]]*\)-\(.*\)$/\3/'`])
+m4trace:configure.in:23: -1- AC_SUBST([host], [$ac_cv_host])
+m4trace:configure.in:23: -1- AC_SUBST([host_cpu], [`echo $ac_cv_host | sed 's/^\([[^-]]*\)-\([[^-]]*\)-\(.*\)$/\1/'`])
+m4trace:configure.in:23: -1- AC_SUBST([host_vendor], [`echo $ac_cv_host | sed 's/^\([[^-]]*\)-\([[^-]]*\)-\(.*\)$/\2/'`])
+m4trace:configure.in:23: -1- AC_SUBST([host_os], [`echo $ac_cv_host | sed 's/^\([[^-]]*\)-\([[^-]]*\)-\(.*\)$/\3/'`])
+m4trace:configure.in:41: -1- AC_SUBST([have_wininet_config])
+m4trace:configure.in:54: -1- AC_SUBST([MUST_BUILD_WININET_CLIENT])
+m4trace:configure.in:62: -1- AC_SUBST([have_curl_config])
+m4trace:configure.in:75: -1- AC_SUBST([MUST_BUILD_CURL_CLIENT])
+m4trace:configure.in:83: -1- AC_SUBST([have_libwww_config])
+m4trace:configure.in:96: -1- AC_SUBST([MUST_BUILD_LIBWWW_CLIENT])
+m4trace:configure.in:107: -1- AC_SUBST([LIBXMLRPC_CLIENT_LA])
+m4trace:configure.in:109: -1- AC_SUBST([CLIENTTEST])
+m4trace:configure.in:111: -1- AC_SUBST([XMLRPC_CLIENT_H])
+m4trace:configure.in:113: -1- AC_SUBST([XMLRPC_TRANSPORT_H])
+m4trace:configure.in:115: -1- AC_SUBST([SYNCH_CLIENT])
+m4trace:configure.in:117: -1- AC_SUBST([ASYNCH_CLIENT])
+m4trace:configure.in:119: -1- AC_SUBST([AUTH_CLIENT])
+m4trace:configure.in:121: -1- AC_SUBST([QUERY_MEERKAT])
+m4trace:configure.in:140: -1- AC_SUBST([ENABLE_ABYSS_SERVER])
+m4trace:configure.in:158: -1- AC_SUBST([ABYSS_SUBDIR])
+m4trace:configure.in:159: -1- AC_SUBST([LIBXMLRPC_ABYSS_SERVER_LA])
+m4trace:configure.in:160: -1- AC_SUBST([SERVERTEST])
+m4trace:configure.in:161: -1- AC_SUBST([VALIDATEE])
+m4trace:configure.in:162: -1- AC_SUBST([XMLRPC_ABYSS_H])
+m4trace:configure.in:163: -1- AC_SUBST([SERVER])
+m4trace:configure.in:172: -1- AC_SUBST([ENABLE_CGI_SERVER])
+m4trace:configure.in:181: -1- AC_SUBST([ENABLE_CPLUSPLUS])
+m4trace:configure.in:202: -1- AC_SUBST([LIBXMLRPC_CPP_A])
+m4trace:configure.in:203: -1- AC_SUBST([CPPTEST])
+m4trace:configure.in:204: -1- AC_SUBST([XMLRPCCPP_H])
+m4trace:configure.in:205: -1- AC_SUBST([XML_RPC_API2CPP_SUBDIR])
+m4trace:configure.in:208: -1- AC_SUBST([FEATURE_LIST])
+m4trace:configure.in:215: -1- AC_PROG_CC
+m4trace:configure.in:215: -1- AC_SUBST([CC])
+m4trace:configure.in:215: -1- AC_SUBST([CFLAGS])
+m4trace:configure.in:215: -1- AC_SUBST([LDFLAGS])
+m4trace:configure.in:215: -1- AC_SUBST([CPPFLAGS])
+m4trace:configure.in:215: -1- AC_SUBST([CC])
+m4trace:configure.in:215: -1- AC_SUBST([ac_ct_CC])
+m4trace:configure.in:215: -1- AC_SUBST([CC])
+m4trace:configure.in:215: -1- AC_SUBST([ac_ct_CC])
+m4trace:configure.in:215: -1- AC_SUBST([CC])
+m4trace:configure.in:215: -1- AC_SUBST([CC])
+m4trace:configure.in:215: -1- AC_SUBST([ac_ct_CC])
+m4trace:configure.in:215: -1- AC_SUBST([EXEEXT], [$ac_cv_exeext])
+m4trace:configure.in:215: -1- AC_SUBST([OBJEXT], [$ac_cv_objext])
+m4trace:configure.in:217: -1- AC_PROG_CXX
+m4trace:configure.in:217: -1- AC_SUBST([CXX])
+m4trace:configure.in:217: -1- AC_SUBST([CXXFLAGS])
+m4trace:configure.in:217: -1- AC_SUBST([LDFLAGS])
+m4trace:configure.in:217: -1- AC_SUBST([CPPFLAGS])
+m4trace:configure.in:217: -1- AC_SUBST([CXX])
+m4trace:configure.in:217: -1- AC_SUBST([ac_ct_CXX])
+m4trace:configure.in:230: -2- AC_CHECK_LIB([socket], [socket])
+m4trace:configure.in:230: -2- AH_OUTPUT([HAVE_LIBSOCKET], [/* Define to 1 if you have the `socket\' library (-lsocket). */
+#undef HAVE_LIBSOCKET])
+m4trace:configure.in:230: -2- AC_DEFINE_TRACE_LITERAL([HAVE_LIBSOCKET])
+m4trace:configure.in:242: -1- AC_SUBST([LSOCKET])
+m4trace:configure.in:253: -1- _m4_warn([obsolete], [The macro `AC_STDC_HEADERS' is obsolete.
+You should run autoupdate.], [autoconf/oldnames.m4:96: AC_STDC_HEADERS is expanded from...
+configure.in:253: the top level])
+m4trace:configure.in:253: -1- AC_HEADER_STDC([])
+m4trace:configure.in:253: -1- AC_PROG_CPP
+m4trace:configure.in:253: -1- AC_SUBST([CPP])
+m4trace:configure.in:253: -1- AC_SUBST([CPPFLAGS])
+m4trace:configure.in:253: -1- AC_SUBST([CPP])
+m4trace:configure.in:253: -1- AC_SUBST([EGREP])
+m4trace:configure.in:253: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS])
+m4trace:configure.in:253: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS])
+m4trace:configure.in:263: -1- AC_CHECK_HEADERS([wchar.h])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_WCHAR_H], [/* Define to 1 if you have the <wchar.h> header file. */
+#undef HAVE_WCHAR_H])
+m4trace:configure.in:263: -1- AC_CHECK_HEADERS([sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h], [], [], [$ac_includes_default])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H])
+m4trace:configure.in:263: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H])
+m4trace:configure.in:270: -1- AC_SUBST([HAVE_WCHAR_H_DEFINE])
+m4trace:configure.in:274: -1- AC_CHECK_HEADERS([sys/filio.h])
+m4trace:configure.in:274: -1- AH_OUTPUT([HAVE_SYS_FILIO_H], [/* Define to 1 if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H])
+m4trace:configure.in:280: -1- AC_SUBST([HAVE_SYS_FILIO_H_DEFINE])
+m4trace:configure.in:284: -1- AC_CHECK_HEADERS([sys/ioctl.h])
+m4trace:configure.in:284: -1- AH_OUTPUT([HAVE_SYS_IOCTL_H], [/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H])
+m4trace:configure.in:290: -1- AC_SUBST([HAVE_SYS_IOCTL_H_DEFINE])
+m4trace:configure.in:295: -1- AC_CHECK_HEADERS([stdarg.h], [], [
+AC_MSG_ERROR(stdarg.h is required to build this library)
+])
+m4trace:configure.in:295: -1- AH_OUTPUT([HAVE_STDARG_H], [/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H])
+m4trace:configure.in:303: -1- AC_TYPE_SIZE_T
+m4trace:configure.in:303: -1- AC_DEFINE_TRACE_LITERAL([size_t])
+m4trace:configure.in:303: -1- AH_OUTPUT([size_t], [/* Define to `unsigned\' if <sys/types.h> does not define. */
+#undef size_t])
+m4trace:configure.in:311: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
+configure.in:311: the top level])
+m4trace:configure.in:318: -1- AC_SUBST([VA_LIST_IS_ARRAY_DEFINE])
+m4trace:configure.in:323: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
+configure.in:323: the top level])
+m4trace:configure.in:330: -1- AC_SUBST([ATTR_UNUSED])
+m4trace:configure.in:342: -1- AC_CHECK_FUNCS([wcsncmp])
+m4trace:configure.in:342: -1- AH_OUTPUT([HAVE_WCSNCMP], [/* Define to 1 if you have the `wcsncmp\' function. */
+#undef HAVE_WCSNCMP])
+m4trace:configure.in:345: -1- AC_CHECK_FUNCS([setgroups])
+m4trace:configure.in:345: -1- AH_OUTPUT([HAVE_SETGROUPS], [/* Define to 1 if you have the `setgroups\' function. */
+#undef HAVE_SETGROUPS])
+m4trace:configure.in:347: -1- AC_CHECK_FUNCS([asprintf])
+m4trace:configure.in:347: -1- AH_OUTPUT([HAVE_ASPRINTF], [/* Define to 1 if you have the `asprintf\' function. */
+#undef HAVE_ASPRINTF])
+m4trace:configure.in:349: -1- AC_CHECK_FUNCS([setenv])
+m4trace:configure.in:349: -1- AH_OUTPUT([HAVE_SETENV], [/* Define to 1 if you have the `setenv\' function. */
+#undef HAVE_SETENV])
+m4trace:configure.in:359: -1- AC_SUBST([DIRECTORY_SEPARATOR])
+m4trace:configure.in:373: -1- AC_SUBST([ENABLE_ABYSS_THREADS])
+m4trace:configure.in:389: -1- AC_SUBST([WININET_CONFIG], [$ac_cv_path_WININET_CONFIG])
+m4trace:configure.in:426: -1- AC_SUBST([WININET_CFLAGS])
+m4trace:configure.in:431: -1- AC_SUBST([WININET_LDADD])
+m4trace:configure.in:445: -1- AC_SUBST([WININET_LIBDIR])
+m4trace:configure.in:447: -1- AC_SUBST([WININET_RPATH])
+m4trace:configure.in:449: -1- AC_SUBST([WININET_WL_RPATH])
+m4trace:configure.in:465: -1- AC_SUBST([LIBWWW_CONFIG], [$ac_cv_path_LIBWWW_CONFIG])
+m4trace:configure.in:502: -1- AC_SUBST([LIBWWW_LDADD])
+m4trace:configure.in:516: -1- AC_SUBST([LIBWWW_LIBDIR])
+m4trace:configure.in:524: -1- AC_SUBST([LIBWWW_RPATH])
+m4trace:configure.in:527: -1- AC_SUBST([LIBWWW_WL_RPATH])
+m4trace:configure.in:540: -1- AC_SUBST([CURL_CONFIG], [$ac_cv_path_CURL_CONFIG])
+m4trace:configure.in:558: -1- AC_SUBST([CURL_LDADD])
+m4trace:configure.in:568: -1- AC_SUBST([CURL_LIBDIR])
+m4trace:configure.in:570: -1- AC_SUBST([CURL_RPATH])
+m4trace:configure.in:572: -1- AC_SUBST([CURL_WL_RPATH])
+m4trace:configure.in:595: -1- AC_SUBST([HAVE_LIBWWW_SSL_DEFINE])
+m4trace:configure.in:605: -1- AC_SUBST([have_xml2_config])
+m4trace:configure.in:611: -1- AC_SUBST([ENABLE_LIBXML2_BACKEND])
+m4trace:configure.in:617: -1- AC_SUBST([C_COMPILER_GNU])
+m4trace:configure.in:619: -1- AC_SUBST([CXX_COMPILER_GNU])
+m4trace:configure.in:623: -1- AC_SUBST([CC_WARN_FLAGS])
+m4trace:configure.in:625: -1- AC_SUBST([CPP_WARN_FLAGS])
+m4trace:configure.in:629: -1- AC_SUBST([BUILDDIR])
+m4trace:configure.in:634: -1- AC_PROG_RANLIB
+m4trace:configure.in:634: -1- AC_SUBST([RANLIB])
+m4trace:configure.in:634: -1- AC_SUBST([ac_ct_RANLIB])
+m4trace:configure.in:634: -1- _m4_warn([obsolete], [The macro `ac_cv_prog_gcc' is obsolete.
+You should run autoupdate.], [autoconf/c.m4:440: ac_cv_prog_gcc is expanded from...
+aclocal.m4:419: AC_PROG_LD is expanded from...
+configure.in:634: AC_PROG_LD is required by...
+aclocal.m4:242: AC_LIBTOOL_SETUP is expanded from...
+configure.in:634: AC_LIBTOOL_SETUP is required by...
+aclocal.m4:158: AC_PROG_LIBTOOL is expanded from...
+aclocal.m4:535: AM_PROG_LIBTOOL is expanded from...
+configure.in:634: the top level])
+m4trace:configure.in:634: -1- AC_PROG_LN_S
+m4trace:configure.in:634: -1- AC_SUBST([LN_S], [$as_ln_s])
+m4trace:configure.in:634: -1- _m4_warn([obsolete], [The macro `ac_cv_prog_gcc' is obsolete.
+You should run autoupdate.], [autoconf/c.m4:440: ac_cv_prog_gcc is expanded from...
+aclocal.m4:242: AC_LIBTOOL_SETUP is expanded from...
+configure.in:634: AC_LIBTOOL_SETUP is required by...
+aclocal.m4:158: AC_PROG_LIBTOOL is expanded from...
+aclocal.m4:535: AM_PROG_LIBTOOL is expanded from...
+configure.in:634: the top level])
+m4trace:configure.in:634: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
+autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
+autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
+aclocal.m4:242: AC_LIBTOOL_SETUP is expanded from...
+configure.in:634: AC_LIBTOOL_SETUP is required by...
+aclocal.m4:158: AC_PROG_LIBTOOL is expanded from...
+aclocal.m4:535: AM_PROG_LIBTOOL is expanded from...
+configure.in:634: the top level])
+m4trace:configure.in:634: -1- AC_SUBST([LIBTOOL])
+m4trace:configure.in:648: -1- AC_CONFIG_FILES([xmlrpc-c-config \
+          xmlrpc-c-config.test \
+          Makefile.config \
+          xmlrpc_config.h \
+          ])
+m4trace:configure.in:648: -1- _m4_warn([obsolete], [AC_OUTPUT should be used without arguments.
+You should run autoupdate.], [])
+m4trace:configure.in:648: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
+m4trace:configure.in:648: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
diff --git a/conf/abyss_root/conf/abyss.conf b/conf/abyss_root/conf/abyss.conf
new file mode 100644 (file)
index 0000000..f9c09f2
--- /dev/null
@@ -0,0 +1,56 @@
+# ABYSS Web Server configuration file
+# (C) Moez Mahfoudh - 2000
+
+# Cases in option names are ignored, 
+# that means that PORT=port=PoRT=..
+
+# When writing paths, do not worry about / or \ use.
+# ABYSS will substitute / with \ on Win32 systems.
+
+# Options which are system specific (such as User) are
+# ignored on systems which do not handle them.
+
+# The Port option tells the server on which TCP port to listen.
+# default is 80
+Port 8080
+
+# The name or #number of the user to run the server as if it is 
+# launched as root (UNIX specific)
+User nobody
+
+# The Server Root (UNIX systems style)
+ServerRoot conf/abyss_root
+
+# The Server Root (Win32 systems style)
+# ServerRoot G:\XML\xmlrpc-c-0.9.5\conf\abyss_root
+
+# The Path option specifies the web files path.
+Path htdocs
+
+# The Default option contains the name of the files the server should
+# look for when only a path is given (e.g. http://myserver/info/).
+Default index.html index.htm INDEX.HTM INDEX.HTML
+
+# The KeepAlive option is used to set the maximum number of requests
+# served using the same persistent connection.
+KeepAlive 10
+
+# The TimeOut option tells the server how much seconds to wait for
+# an idle connection before closing it.
+TimeOut 10
+
+# The MimeTypes option specifies the location of the file
+# containing the mapping of MIME types and files extensions
+MimeTypes conf/mime.types
+
+# The path of the log file
+LogFile log/access.log
+
+# The file where the pid of the server is logged (UNIX specific)
+PidFile log/abyss.pid
+
+# If AdvertiseServer if set to no, then no server field would be
+# appended to the responses. This is the way to make the server
+# identity unknown to some malicious people which can profit from
+# well known security holes in the software to crash it.
+AdvertiseServer yes
diff --git a/conf/abyss_root/conf/mime.types b/conf/abyss_root/conf/mime.types
new file mode 100644 (file)
index 0000000..d53db0f
--- /dev/null
@@ -0,0 +1,276 @@
+# This is a comment. I love comments.
+
+# This file controls what Internet media types are sent to the client for
+# given file extension(s).  Sending the correct media type to the client
+# is important so they know how to handle the content of the file.
+# Extra types can either be added here or by using an AddType directive
+# in your config files. For more information about Internet media types,
+# please read RFC 2045, 2046, 2047, 2048, and 2077.  The Internet media type
+# registry is at <ftp://ftp.iana.org/in-notes/iana/assignments/media-types/>.
+
+# MIME type                    Extension
+application/EDI-Consent
+application/EDI-X12
+application/EDIFACT
+application/activemessage
+application/andrew-inset       ez
+application/applefile
+application/atomicmail
+application/cals-1840
+application/commonground
+application/cybercash
+application/dca-rft
+application/dec-dx
+application/eshop
+application/hyperstudio
+application/iges
+application/mac-binhex40       hqx
+application/mac-compactpro     cpt
+application/macwriteii
+application/marc
+application/mathematica
+application/msword             doc
+application/news-message-id
+application/news-transmission
+application/octet-stream       bin dms lha lzh exe class
+application/oda                        oda
+application/pdf                        pdf
+application/pgp-encrypted
+application/pgp-keys
+application/pgp-signature
+application/pkcs10
+application/pkcs7-mime
+application/pkcs7-signature
+application/postscript         ai eps ps
+application/prs.alvestrand.titrax-sheet
+application/prs.cww
+application/prs.nprend
+application/remote-printing
+application/riscos
+application/rtf                        rtf
+application/set-payment
+application/set-payment-initiation
+application/set-registration
+application/set-registration-initiation
+application/sgml
+application/sgml-open-catalog
+application/slate
+application/smil               smi smil
+application/vemmi
+application/vnd.3M.Post-it-Notes
+application/vnd.FloGraphIt
+application/vnd.acucobol
+application/vnd.anser-web-certificate-issue-initiation
+application/vnd.anser-web-funds-transfer-initiation
+application/vnd.audiograph
+application/vnd.businessobjects
+application/vnd.claymore
+application/vnd.comsocaller
+application/vnd.dna
+application/vnd.dxr
+application/vnd.ecdis-update
+application/vnd.ecowin.chart
+application/vnd.ecowin.filerequest
+application/vnd.ecowin.fileupdate
+application/vnd.ecowin.series
+application/vnd.ecowin.seriesrequest
+application/vnd.ecowin.seriesupdate
+application/vnd.enliven
+application/vnd.epson.salt
+application/vnd.fdf
+application/vnd.ffsns
+application/vnd.framemaker
+application/vnd.fujitsu.oasys
+application/vnd.fujitsu.oasys2
+application/vnd.fujitsu.oasys3
+application/vnd.fujitsu.oasysgp
+application/vnd.fujitsu.oasysprs
+application/vnd.fujixerox.docuworks
+application/vnd.hp-HPGL
+application/vnd.hp-PCL
+application/vnd.hp-PCLXL
+application/vnd.hp-hps
+application/vnd.ibm.MiniPay
+application/vnd.ibm.modcap
+application/vnd.intercon.formnet
+application/vnd.intertrust.digibox
+application/vnd.intertrust.nncp
+application/vnd.is-xpr
+application/vnd.japannet-directory-service
+application/vnd.japannet-jpnstore-wakeup
+application/vnd.japannet-payment-wakeup
+application/vnd.japannet-registration
+application/vnd.japannet-registration-wakeup
+application/vnd.japannet-setstore-wakeup
+application/vnd.japannet-verification
+application/vnd.japannet-verification-wakeup
+application/vnd.koan
+application/vnd.lotus-1-2-3
+application/vnd.lotus-approach
+application/vnd.lotus-freelance
+application/vnd.lotus-organizer
+application/vnd.lotus-screencam
+application/vnd.lotus-wordpro
+application/vnd.meridian-slingshot
+application/vnd.mif            mif
+application/vnd.minisoft-hp3000-save
+application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.ms-artgalry
+application/vnd.ms-asf
+application/vnd.ms-excel       xls
+application/vnd.ms-powerpoint  ppt
+application/vnd.ms-project
+application/vnd.ms-tnef
+application/vnd.ms-works
+application/vnd.music-niff
+application/vnd.musician
+application/vnd.netfpx
+application/vnd.noblenet-directory
+application/vnd.noblenet-sealer
+application/vnd.noblenet-web
+application/vnd.novadigm.EDM
+application/vnd.novadigm.EDX
+application/vnd.novadigm.EXT
+application/vnd.osa.netdeploy
+application/vnd.powerbuilder6
+application/vnd.powerbuilder6-s
+application/vnd.rapid
+application/vnd.seemail
+application/vnd.shana.informed.formtemplate
+application/vnd.shana.informed.interchange
+application/vnd.shana.informed.package
+application/vnd.street-stream
+application/vnd.svd
+application/vnd.swiftview-ics
+application/vnd.truedoc
+application/vnd.visio
+application/vnd.webturbo
+application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf
+application/vnd.xara
+application/vnd.yellowriver-custom-menu
+application/wita
+application/wordperfect5.1
+application/x-bcpio            bcpio
+application/x-cdlink           vcd
+application/x-chess-pgn                pgn
+application/x-compress
+application/x-cpio             cpio
+application/x-csh              csh
+application/x-director         dcr dir dxr
+application/x-dvi              dvi
+application/x-futuresplash     spl
+application/x-gtar             gtar
+application/x-gzip
+application/x-hdf              hdf
+application/x-javascript       js
+application/x-koan             skp skd skt skm
+application/x-latex            latex
+application/x-netcdf           nc cdf
+application/x-sh               sh
+application/x-shar             shar
+application/x-shockwave-flash  swf
+application/x-stuffit          sit
+application/x-sv4cpio          sv4cpio
+application/x-sv4crc           sv4crc
+application/x-tar              tar
+application/x-tcl              tcl
+application/x-tex              tex
+application/x-texinfo          texinfo texi
+application/x-troff            t tr roff
+application/x-troff-man                man
+application/x-troff-me         me
+application/x-troff-ms         ms
+application/x-ustar            ustar
+application/x-wais-source      src
+application/x400-bp
+application/xml
+application/zip                        zip
+audio/32kadpcm
+audio/basic                    au snd
+audio/midi                     mid midi kar
+audio/mpeg                     mpga mp2 mp3
+audio/vnd.qcelp
+audio/x-aiff                   aif aiff aifc
+audio/x-pn-realaudio           ram rm
+audio/x-pn-realaudio-plugin    rpm
+audio/x-realaudio              ra
+audio/x-wav                    wav
+chemical/x-pdb                 pdb xyz
+image/bmp                      bmp
+image/cgm
+image/g3fax
+image/gif                      gif
+image/ief                      ief
+image/jpeg                     jpeg jpg jpe
+image/naplps
+image/png                      png
+image/prs.btif
+image/tiff                     tiff tif
+image/vnd.dwg
+image/vnd.dxf
+image/vnd.fpx
+image/vnd.net-fpx
+image/vnd.svf
+image/vnd.xiff
+image/x-cmu-raster             ras
+image/x-portable-anymap                pnm
+image/x-portable-bitmap                pbm
+image/x-portable-graymap       pgm
+image/x-portable-pixmap                ppm
+image/x-rgb                    rgb
+image/x-xbitmap                        xbm
+image/x-xpixmap                        xpm
+image/x-xwindowdump            xwd
+message/delivery-status
+message/disposition-notification
+message/external-body
+message/http
+message/news
+message/partial
+message/rfc822
+model/iges                     igs iges
+model/mesh                     msh mesh silo
+model/vnd.dwf
+model/vrml                     wrl vrml
+multipart/alternative
+multipart/appledouble
+multipart/byteranges
+multipart/digest
+multipart/encrypted
+multipart/form-data
+multipart/header-set
+multipart/mixed
+multipart/parallel
+multipart/related
+multipart/report
+multipart/signed
+multipart/voice-message
+text/css                       css
+text/directory
+text/enriched
+text/html                      html htm
+text/plain                     asc txt
+text/prs.lines.tag
+text/rfc822-headers
+text/richtext                  rtx
+text/rtf                       rtf
+text/sgml                      sgml sgm
+text/tab-separated-values      tsv
+text/uri-list
+text/vnd.abc
+text/vnd.flatland.3dml
+text/vnd.fmi.flexstor
+text/vnd.in3d.3dml
+text/vnd.in3d.spot
+text/vnd.latex-z
+text/x-setext                  etx
+text/xml                       xml
+video/mpeg                     mpeg mpg mpe
+video/quicktime                        qt mov
+video/vnd.motorola.video
+video/vnd.motorola.videop
+video/vnd.vivo
+video/x-msvideo                        avi
+video/x-sgi-movie              movie
+x-conference/x-cooltalk                ice
diff --git a/conf/abyss_root/htdocs/index.htm b/conf/abyss_root/htdocs/index.htm
new file mode 100644 (file)
index 0000000..f0369a5
--- /dev/null
@@ -0,0 +1,21 @@
+<HTML>
+<HEAD>
+<TITLE>ABYSS is working !!!</TITLE>
+</HEAD>
+<BODY bgColor=#80a0f0 text=#000000>
+<H1 align=center>Congratulations, ABYSS is working !!!</H1>
+<BR>
+<P>
+<B>ABYSS</B> Web Server is working correctly on your system. You should now change this
+page with yours.
+<BR>
+Please include in your web pages (at least the first), the <b><i>'Powered by ABYSS'</i></b>
+banner to promote the use of <B>ABYSS</B>.
+</P>
+<hr>
+<P>
+<CENTER><FONT size=-1>
+Copyright Â© 2000 <A href="mailto:mmoez@bigfoot.com">Moez Mahfoudh</A>. All rights reserved.
+</FONT>
+<BR><BR><A href="http://abyss.linuxave.net/"><IMG border=0 src="pwrabyss.gif"></A></center></P>
+</BODY></HTML>
diff --git a/conf/abyss_root/htdocs/pwrabyss.gif b/conf/abyss_root/htdocs/pwrabyss.gif
new file mode 100644 (file)
index 0000000..9a4a3a3
Binary files /dev/null and b/conf/abyss_root/htdocs/pwrabyss.gif differ
diff --git a/config.guess b/config.guess
new file mode 100755 (executable)
index 0000000..dd1688b
--- /dev/null
@@ -0,0 +1,1459 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2004-06-11'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep __ELF__ >/dev/null
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit 0 ;;
+    amd64:OpenBSD:*:*)
+       echo x86_64-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    amiga:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    cats:OpenBSD:*:*)
+       echo arm-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hp300:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    luna88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    pmax:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sgi:OpenBSD:*:*)
+       echo mipseb-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:OpenBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:MirBSD:*:*)
+       echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit 0 ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit 0 ;;
+    Alpha*:OpenVMS:*:*)
+       echo alpha-hp-vms
+       exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit 0 ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit 0 ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit 0 ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit 0 ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit 0 ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit 0 ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit 0 ;;
+    DRS?6000:UNIX_SV:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7 && exit 0 ;;
+       esac ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    i86pc:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit 0 ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit 0 ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit 0 ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c \
+         && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+         && exit 0
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit 0 ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit 0 ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit 0 ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit 0 ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit 0 ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit 0 ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit 0 ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit 0 ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+       exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit 0 ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit 0 ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+               echo rs6000-ibm-aix3.2.5
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit 0 ;;
+    *:AIX:*:[45])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit 0 ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           # avoid double evaluation of $set_cc_for_build
+           test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+       echo unknown-hitachi-hiuxwe2
+       exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit 0 ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit 0 ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit 0 ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    *:UNICOS/mp:*:*)
+       echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:FreeBSD:*:*)
+       # Determine whether the default compiler uses glibc.
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #if __GLIBC__ >= 2
+       LIBC=gnu
+       #else
+       LIBC=
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       # GNU/KFreeBSD systems have a "k" prefix to indicate we are using
+       # FreeBSD's kernel, but not the complete OS.
+       case ${LIBC} in gnu) kernel_only='k' ;; esac
+       echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+       exit 0 ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit 0 ;;
+    i*:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit 0 ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit 0 ;;
+    x86:Interix*:[34]*)
+       echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+       exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit 0 ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit 0 ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit 0 ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit 0 ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit 0 ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit 0 ;;
+    arm*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit 0 ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    mips:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips
+       #undef mipsel
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mipsel
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+       ;;
+    mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips64
+       #undef mips64el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mips64el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips64
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+       ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit 0 ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit 0 ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+       objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit 0 ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit 0 ;;
+    i*86:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us. cd to the root directory to prevent
+       # problems with other programs or directories called `ld' in the path.
+       # Set LC_ALL=C to ensure ld outputs messages in English.
+       ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+                        | sed -ne '/supported targets:/!d
+                                   s/[         ][      ]*/ /g
+                                   s/.*supported targets: *//
+                                   s/ .*//
+                                   p'`
+        case "$ld_supported_targets" in
+         elf32-i386)
+               TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+               ;;
+         a.out-i386-linux)
+               echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+               exit 0 ;;
+         coff-i386)
+               echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+               exit 0 ;;
+         "")
+               # Either a pre-BFD a.out linker (linux-gnuoldld) or
+               # one that does not give us useful --help.
+               echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+               exit 0 ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #ifdef __INTEL_COMPILER
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+       test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+       ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit 0 ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit 0 ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit 0 ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit 0 ;;
+       i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit 0 ;;
+    i*86:*:5:[78]*)
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit 0 ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit 0 ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+       echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit 0 ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit 0 ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit 0 ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit 0 ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit 0 ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit 0 ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit 0 ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit 0 ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit 0 ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit 0 ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Darwin:*:*)
+       case `uname -p` in
+           *86) UNAME_PROCESSOR=i686 ;;
+           powerpc) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit 0 ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit 0 ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit 0 ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit 0 ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit 0 ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit 0 ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit 0 ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit 0 ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit 0 ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit 0 ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit 0 ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit 0 ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit 0 ;;
+    c34*)
+       echo c34-convex-bsd
+       exit 0 ;;
+    c38*)
+       echo c38-convex-bsd
+       exit 0 ;;
+    c4*)
+       echo c4-convex-bsd
+       exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.sub b/config.sub
new file mode 100755 (executable)
index 0000000..ba33103
--- /dev/null
@@ -0,0 +1,1549 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2004-03-12'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+  kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis)
+               os=
+               basic_machine=$1
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+       | c4x | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | m32r | m32rle | m68000 | m68k | m88k | mcore \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64vr | mips64vrel \
+       | mips64orion | mips64orionel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | msp430 \
+       | ns16k | ns32k \
+       | openrisc | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
+       | strongarm \
+       | tahoe | thumb | tic4x | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xscale | xstormy16 | xtensa \
+       | z8k)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+       | avr-* \
+       | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | mcore-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipstx39-* | mipstx39el-* \
+       | msp430-* \
+       | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+       | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+       | xtensa-* \
+       | ymp-* \
+       | z8k-*)
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       cr16c)
+               basic_machine=cr16c-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       mmix*)
+               basic_machine=mmix-knuth
+               os=-mmixware
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nv1)
+               basic_machine=nv1-cray
+               os=-unicosmp
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       or32 | or32-*)
+               basic_machine=or32-unknown
+               os=-coff
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tic55x | c55x*)
+               basic_machine=tic55x-unknown
+               os=-coff
+               ;;
+       tic6x | c6x*)
+               basic_machine=tic6x-unknown
+               os=-coff
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b)
+               basic_machine=sparc-sun
+               ;;
+       cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+        -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+        -tpf*)
+               os=-tpf
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -kaos*)
+               os=-kaos
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+    c4x-* | tic4x-*)
+        os=-coff
+        ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+       pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+       *-gould)
+               os=-sysv
+               ;;
+       *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+       *-sgi)
+               os=-irix
+               ;;
+       *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..b83f07d
--- /dev/null
+++ b/configure
@@ -0,0 +1,7573 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="include/xmlrpc-c/base.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO SET_MAKE VERSION_INFO build build_cpu build_vendor build_os host host_cpu host_vendor host_os have_wininet_config MUST_BUILD_WININET_CLIENT have_curl_config MUST_BUILD_CURL_CLIENT have_libwww_config MUST_BUILD_LIBWWW_CLIENT LIBXMLRPC_CLIENT_LA CLIENTTEST XMLRPC_CLIENT_H XMLRPC_TRANSPORT_H SYNCH_CLIENT ASYNCH_CLIENT AUTH_CLIENT QUERY_MEERKAT ENABLE_ABYSS_SERVER ABYSS_SUBDIR LIBXMLRPC_ABYSS_SERVER_LA SERVERTEST VALIDATEE XMLRPC_ABYSS_H SERVER ENABLE_CGI_SERVER ENABLE_CPLUSPLUS LIBXMLRPC_CPP_A CPPTEST XMLRPCCPP_H XML_RPC_API2CPP_SUBDIR FEATURE_LIST CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX LSOCKET CPP EGREP HAVE_WCHAR_H_DEFINE HAVE_SYS_FILIO_H_DEFINE HAVE_SYS_IOCTL_H_DEFINE VA_LIST_IS_ARRAY_DEFINE ATTR_UNUSED DIRECTORY_SEPARATOR ENABLE_ABYSS_THREADS WININET_CONFIG WININET_CFLAGS WININET_LDADD WININET_LIBDIR WININET_RPATH WININET_WL_RPATH LIBWWW_CONFIG LIBWWW_LDADD LIBWWW_LIBDIR LIBWWW_RPATH LIBWWW_WL_RPATH CURL_CONFIG CURL_LDADD CURL_LIBDIR CURL_RPATH CURL_WL_RPATH HAVE_LIBWWW_SSL_DEFINE have_xml2_config ENABLE_LIBXML2_BACKEND C_COMPILER_GNU CXX_COMPILER_GNU CC_WARN_FLAGS CPP_WARN_FLAGS BUILDDIR RANLIB ac_ct_RANLIB LN_S LIBTOOL LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+             localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$0" : 'X\(//\)[^/]' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                         [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                         [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-wininet-client  Don't build the Wininet client transport
+  --disable-curl-client     Don't build the Curl client transport
+  --disable-libwww-client   Don't build the Libwww client transport
+  --disable-abyss-server    Don't build the Abyss server module
+  --disable-cgi-server      Don't build the CGI server module
+  --disable-cplusplus       Don't build the C++ wrapper classes or tools
+  --disable-abyss-threads   Use fork in Abyss instead of pthreads
+  --enable-libxml2-backend  Use libxml2 instead of built-in expat
+  --enable-shared=PKGS  build shared libraries default=yes
+  --enable-static=PKGS  build static libraries default=yes
+  --enable-fast-install=PKGS  optimize for fast installation default=yes
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-libwww-ssl       Include libwww SSL capability.
+
+  --with-gnu-ld           assume the C compiler uses GNU ld default=no
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+          test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=$`echo $ac_var`
+       echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+       ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+          ac_config_headers="$ac_config_headers xmlrpc_amconfig.h"
+
+          ac_config_commands="$ac_config_commands default-1"
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "$*" != "X $srcdir/configure conftestfile" \
+      && test "$*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f conftest*
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+       @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+PACKAGE=xmlrpc-c
+
+VERSION=1.06.32
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo "$as_me:$LINENO: checking for working aclocal" >&5
+echo $ECHO_N "checking for working aclocal... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+   ACLOCAL=aclocal
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   ACLOCAL="$missing_dir/missing aclocal"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+echo "$as_me:$LINENO: checking for working autoconf" >&5
+echo $ECHO_N "checking for working autoconf... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+   AUTOCONF=autoconf
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   AUTOCONF="$missing_dir/missing autoconf"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+echo "$as_me:$LINENO: checking for working automake" >&5
+echo $ECHO_N "checking for working automake... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+   AUTOMAKE=automake
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   AUTOMAKE="$missing_dir/missing automake"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+echo "$as_me:$LINENO: checking for working autoheader" >&5
+echo $ECHO_N "checking for working autoheader... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+   AUTOHEADER=autoheader
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   AUTOHEADER="$missing_dir/missing autoheader"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+echo "$as_me:$LINENO: checking for working makeinfo" >&5
+echo $ECHO_N "checking for working makeinfo... $ECHO_C" >&6
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+   MAKEINFO=makeinfo
+   echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+else
+   MAKEINFO="$missing_dir/missing makeinfo"
+   echo "$as_me:$LINENO: result: missing" >&5
+echo "${ECHO_T}missing" >&6
+fi
+
+
+
+VERSION_INFO="-version-info 7:0:6"
+
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+
+test -z "$target" && target=NONE
+
+
+FEATURE_LIST=
+
+# Check whether --enable-wininet-client or --disable-wininet-client was given.
+if test "${enable_wininet_client+set}" = set; then
+  enableval="$enable_wininet_client"
+
+else
+  enable_wininet_client=maybe
+fi;
+
+if test $enable_wininet_client = maybe; then
+  # Extract the first word of "wininet-config", so it can be a program name with args.
+set dummy wininet-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_have_wininet_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$have_wininet_config"; then
+  ac_cv_prog_have_wininet_config="$have_wininet_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_wininet_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_have_wininet_config" && ac_cv_prog_have_wininet_config="no"
+fi
+fi
+have_wininet_config=$ac_cv_prog_have_wininet_config
+if test -n "$have_wininet_config"; then
+  echo "$as_me:$LINENO: result: $have_wininet_config" >&5
+echo "${ECHO_T}$have_wininet_config" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  if test $have_wininet_config = no; then
+    { echo "$as_me:$LINENO: You don't appear to have Wininet installed (no working wininet-config in your command search path), so we will not build the Wininet client XML transport" >&5
+echo "$as_me: You don't appear to have Wininet installed (no working wininet-config in your command search path), so we will not build the Wininet client XML transport" >&6;}
+    MUST_BUILD_WININET_CLIENT=no
+  else
+    MUST_BUILD_WININET_CLIENT=yes
+  fi
+else
+  MUST_BUILD_WININET_CLIENT=$enable_wininet_client
+fi
+
+echo "$as_me:$LINENO: checking whether to build Wininet client XML transport module" >&5
+echo $ECHO_N "checking whether to build Wininet client XML transport module... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $MUST_BUILD_WININET_CLIENT" >&5
+echo "${ECHO_T}$MUST_BUILD_WININET_CLIENT" >&6
+
+
+
+# Check whether --enable-curl-client or --disable-curl-client was given.
+if test "${enable_curl_client+set}" = set; then
+  enableval="$enable_curl_client"
+
+else
+  enable_curl_client=maybe
+fi;
+
+if test $enable_curl_client = maybe; then
+  # Extract the first word of "curl-config", so it can be a program name with args.
+set dummy curl-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_have_curl_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$have_curl_config"; then
+  ac_cv_prog_have_curl_config="$have_curl_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_curl_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_have_curl_config" && ac_cv_prog_have_curl_config="no"
+fi
+fi
+have_curl_config=$ac_cv_prog_have_curl_config
+if test -n "$have_curl_config"; then
+  echo "$as_me:$LINENO: result: $have_curl_config" >&5
+echo "${ECHO_T}$have_curl_config" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  if test $have_curl_config = no; then
+    { echo "$as_me:$LINENO: You don't appear to have Curl installed (no working curl-config in your command search path), so we will not build the Curl client XML transport" >&5
+echo "$as_me: You don't appear to have Curl installed (no working curl-config in your command search path), so we will not build the Curl client XML transport" >&6;}
+    MUST_BUILD_CURL_CLIENT=no
+  else
+    MUST_BUILD_CURL_CLIENT=yes
+  fi
+else
+  MUST_BUILD_CURL_CLIENT=$enable_curl_client
+fi
+
+echo "$as_me:$LINENO: checking whether to build Curl client XML transport module" >&5
+echo $ECHO_N "checking whether to build Curl client XML transport module... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $MUST_BUILD_CURL_CLIENT" >&5
+echo "${ECHO_T}$MUST_BUILD_CURL_CLIENT" >&6
+
+
+
+# Check whether --enable-libwww-client or --disable-libwww-client was given.
+if test "${enable_libwww_client+set}" = set; then
+  enableval="$enable_libwww_client"
+
+else
+  enable_libwww_client=maybe
+fi;
+
+if test $enable_libwww_client = maybe; then
+  # Extract the first word of "libwww-config", so it can be a program name with args.
+set dummy libwww-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_have_libwww_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$have_libwww_config"; then
+  ac_cv_prog_have_libwww_config="$have_libwww_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_libwww_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_have_libwww_config" && ac_cv_prog_have_libwww_config="no"
+fi
+fi
+have_libwww_config=$ac_cv_prog_have_libwww_config
+if test -n "$have_libwww_config"; then
+  echo "$as_me:$LINENO: result: $have_libwww_config" >&5
+echo "${ECHO_T}$have_libwww_config" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  if test $have_libwww_config = no; then
+    { echo "$as_me:$LINENO: You don't appear to have Libwww installed (no working libwww-config in your command search path), so we will not build the Libwww client XML transport" >&5
+echo "$as_me: You don't appear to have Libwww installed (no working libwww-config in your command search path), so we will not build the Libwww client XML transport" >&6;}
+    MUST_BUILD_LIBWWW_CLIENT=no
+  else
+    MUST_BUILD_LIBWWW_CLIENT=yes
+  fi
+else
+  MUST_BUILD_LIBWWW_CLIENT=$enable_libwww_client
+fi
+
+echo "$as_me:$LINENO: checking whether to build Libwww client XML transport module" >&5
+echo $ECHO_N "checking whether to build Libwww client XML transport module... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $MUST_BUILD_LIBWWW_CLIENT" >&5
+echo "${ECHO_T}$MUST_BUILD_LIBWWW_CLIENT" >&6
+
+
+
+if test "$MUST_BUILD_WININET_CLIENT $MUST_BUILD_CURL_CLIENT $MUST_BUILD_LIBWWW_CLIENT" = "no no no"; then
+  { echo "$as_me:$LINENO: We are not building any client XML transport, therefore we will not build the client library at all." >&5
+echo "$as_me: We are not building any client XML transport, therefore we will not build the client library at all." >&6;}
+fi
+
+
+
+LIBXMLRPC_CLIENT_LA=libxmlrpc_client.la
+
+CLIENTTEST=clienttest
+
+XMLRPC_CLIENT_H=xmlrpc_client.h
+
+XMLRPC_TRANSPORT_H=xmlrpc_transport.h
+
+SYNCH_CLIENT=synch_client
+
+ASYNCH_CLIENT=asynch_client
+
+AUTH_CLIENT=auth_client
+
+QUERY_MEERKAT=query-meerkat
+
+
+if test $MUST_BUILD_WININET_CLIENT = yes; then
+    FEATURE_LIST="wininet-client $FEATURE_LIST"
+fi
+if test $MUST_BUILD_CURL_CLIENT = yes; then
+    FEATURE_LIST="curl-client $FEATURE_LIST"
+fi
+if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+    FEATURE_LIST="libwww-client $FEATURE_LIST"
+fi
+
+echo "$as_me:$LINENO: checking whether to build Abyss server module" >&5
+echo $ECHO_N "checking whether to build Abyss server module... $ECHO_C" >&6
+# Check whether --enable-abyss-server or --disable-abyss-server was given.
+if test "${enable_abyss_server+set}" = set; then
+  enableval="$enable_abyss_server"
+
+else
+  enable_abyss_server=yes
+fi;
+echo "$as_me:$LINENO: result: $enable_abyss_server" >&5
+echo "${ECHO_T}$enable_abyss_server" >&6
+ENABLE_ABYSS_SERVER=$enable_abyss_server
+
+
+ABYSS_SUBDIR=
+LIBXMLRPC_ABYSS_SERVER_LA=
+SERVERTEST=
+VALIDATEE=
+XMLRPC_ABYSS_H=
+SERVER=
+if test x"$enable_abyss_server" != xno; then
+    FEATURE_LIST="abyss-server $FEATURE_LIST"
+    ABYSS_SUBDIR=abyss
+    LIBXMLRPC_ABYSS_SERVER_LA=libxmlrpc_abyss_server.la
+    SERVERTEST=servertest
+    VALIDATEE=validatee
+    XMLRPC_ABYSS_H=xmlrpc_abyss.h
+    SERVER=server
+fi
+
+
+
+
+
+
+
+echo "$as_me:$LINENO: checking whether to build CGI server module" >&5
+echo $ECHO_N "checking whether to build CGI server module... $ECHO_C" >&6
+# Check whether --enable-cgi-server or --disable-cgi-server was given.
+if test "${enable_cgi_server+set}" = set; then
+  enableval="$enable_cgi_server"
+
+else
+  enable_cgi_server=yes
+fi;
+echo "$as_me:$LINENO: result: $enable_cgi_server" >&5
+echo "${ECHO_T}$enable_cgi_server" >&6
+ENABLE_CGI_SERVER=$enable_cgi_server
+
+
+echo "$as_me:$LINENO: checking whether to build C++ wrappers and tools" >&5
+echo $ECHO_N "checking whether to build C++ wrappers and tools... $ECHO_C" >&6
+# Check whether --enable-cplusplus or --disable-cplusplus was given.
+if test "${enable_cplusplus+set}" = set; then
+  enableval="$enable_cplusplus"
+
+else
+  enable_cplusplus=yes
+fi;
+echo "$as_me:$LINENO: result: $enable_cplusplus" >&5
+echo "${ECHO_T}$enable_cplusplus" >&6
+ENABLE_CPLUSPLUS=$enable_cplusplus
+
+
+LIBXMLRPC_CPP_A=
+CPPTEST=
+XMLRPCCPP_H=
+XML_RPC_API2CPP_SUBDIR=
+MEERKAT_APP_LIST=
+INTEROP_CLIENT_SUBDIR=
+if test x"$enable_cplusplus" != xno; then
+    FEATURE_LIST="c++ $FEATURE_LIST"
+    LIBXMLRPC_CPP_A=libxmlrpc_cpp.a
+    CPPTEST=cpptest
+    XMLRPCCPP_H=XmlRpcCpp.h
+
+    if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+        XML_RPC_API2CPP_SUBDIR=xml-rpc-api2cpp
+    elif test $MUST_BUILD_CURL_CLIENT = yes; then
+        XML_RPC_API2CPP_SUBDIR=xml-rpc-api2cpp
+    fi
+fi
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+       ;;
+    conftest.$ac_ext )
+       # This is the source file.
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       # FIXME: I believe we export ac_cv_exeext for Libtool,
+       # but it would be cool to find out if it's true.  Does anybody
+       # maintain Libtool? --akim.
+       export ac_cv_exeext
+       break;;
+    * )
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         export ac_cv_exeext
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX                  -qlanglvl=ansi
+# Ultrix and OSF/1     -std1
+# HP-UX 10.20 and later        -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4                 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test x"$enable_cplusplus" != xno; then
+    ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+  CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+
+
+
+# Code by albert chin <china@thewrittenword.com> to check for various
+# oddball networking libraries.  Solaris and some other operating systems
+# hide their networking code in various places.  (Yes, this links too many
+# of our libraries against -lsocket, but a finer-grained mechanism would
+# require too much testing.)
+echo "$as_me:$LINENO: checking for socket" >&5
+echo $ECHO_N "checking for socket... $ECHO_C" >&6
+if test "${ac_cv_func_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define socket to an innocuous variant, in case <limits.h> declares socket.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define socket innocuous_socket
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char socket (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef socket
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_socket) || defined (__stub___socket)
+choke me
+#else
+char (*f) () = socket;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != socket;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_socket=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_socket" >&5
+echo "${ECHO_T}$ac_cv_func_socket" >&6
+if test $ac_cv_func_socket = yes; then
+  :
+else
+
+echo "$as_me:$LINENO: checking for socket in -lsocket" >&5
+echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+int
+main ()
+{
+socket ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_socket_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_socket_socket=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6
+if test $ac_cv_lib_socket_socket = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+  LIBS="-lsocket $LIBS"
+
+fi
+
+fi
+
+
+# Above sets LIBS, which is not all that useful because we don't want
+# to include every library in every link.  It also sets
+# ac_cv_lib_socket_socket, which we use to pass more specific information
+# to the configuration files.
+
+if test x"$ac_cv_lib_socket_socket" = xyes; then
+  LSOCKET=-lsocket
+else
+  LSOCKET=
+fi
+
+
+# For some reason, we don't seem to need this on Solaris.  If you do
+# need it, go ahead and try it.
+# AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent))
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in wchar.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+if test x"$ac_cv_header_wchar_h" = xyes; then
+  HAVE_WCHAR_H_DEFINE=1
+else
+  HAVE_WCHAR_H_DEFINE=0
+fi
+
+
+# Needed by Abyss on Solaris:
+
+
+for ac_header in sys/filio.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+if test x"$ac_cv_header_sys_filio_h" = xyes; then
+  HAVE_SYS_FILIO_H_DEFINE=1
+else
+  HAVE_SYS_FILIO_H_DEFINE=0
+fi
+
+
+# Needed by Abyss on Solaris:
+
+
+for ac_header in sys/ioctl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+if test x"$ac_cv_header_sys_ioctl_h" = xyes; then
+  HAVE_SYS_IOCTL_H_DEFINE=1
+else
+  HAVE_SYS_IOCTL_H_DEFINE=0
+fi
+
+
+
+
+for ac_header in stdarg.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+{ { echo "$as_me:$LINENO: error: stdarg.h is required to build this library" >&5
+echo "$as_me: error: stdarg.h is required to build this library" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+
+done
+
+
+
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+  return 0;
+if (sizeof (size_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
+_ACEOF
+
+fi
+
+
+va_list_is_array=no
+echo "$as_me:$LINENO: checking whether va_list is an array" >&5
+echo $ECHO_N "checking whether va_list is an array... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdarg.h>
+
+int
+main ()
+{
+va_list list1, list2; list1 = list2;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+va_list_is_array=yes
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $va_list_is_array" >&5
+echo "${ECHO_T}$va_list_is_array" >&6
+if test x"$va_list_is_array" = xyes; then
+  VA_LIST_IS_ARRAY_DEFINE=1
+else
+  VA_LIST_IS_ARRAY_DEFINE=0
+fi
+
+
+echo "$as_me:$LINENO: checking whether compiler has __attribute__" >&5
+echo $ECHO_N "checking whether compiler has __attribute__... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+int x __attribute__((__unused__));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  compiler_has_attribute=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+compiler_has_attribute=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $compiler_has_attribute" >&5
+echo "${ECHO_T}$compiler_has_attribute" >&6
+if test x"$compiler_has_attribute" = xyes; then
+    ATTR_UNUSED="__attribute__((__unused__))"
+else
+    ATTR_UNUSED=
+fi
+
+
+
+
+echo "$as_me:$LINENO: checking for vsnprintf" >&5
+echo $ECHO_N "checking for vsnprintf... $ECHO_C" >&6
+if test "${ac_cv_func_vsnprintf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define vsnprintf to an innocuous variant, in case <limits.h> declares vsnprintf.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define vsnprintf innocuous_vsnprintf
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char vsnprintf (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef vsnprintf
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char vsnprintf ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_vsnprintf) || defined (__stub___vsnprintf)
+choke me
+#else
+char (*f) () = vsnprintf;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != vsnprintf;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_vsnprintf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_vsnprintf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_vsnprintf" >&5
+echo "${ECHO_T}$ac_cv_func_vsnprintf" >&6
+if test $ac_cv_func_vsnprintf = yes; then
+  :
+else
+
+{ { echo "$as_me:$LINENO: error: your C library does not provide vsnprintf" >&5
+echo "$as_me: error: your C library does not provide vsnprintf" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+
+
+
+for ac_func in wcsncmp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+for ac_func in setgroups
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+for ac_func in asprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+for ac_func in setenv
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+DIRECTORY_SEPARATOR="/"
+
+
+
+
+echo "$as_me:$LINENO: checking whether to use Abyss pthread function" >&5
+echo $ECHO_N "checking whether to use Abyss pthread function... $ECHO_C" >&6
+# Check whether --enable-abyss-threads or --disable-abyss-threads was given.
+if test "${enable_abyss_threads+set}" = set; then
+  enableval="$enable_abyss_threads"
+
+else
+  enable_abyss_threads=yes
+fi;
+echo "$as_me:$LINENO: result: $enable_abyss_threads" >&5
+echo "${ECHO_T}$enable_abyss_threads" >&6
+
+ENABLE_ABYSS_THREADS=$enable_abyss_threads
+
+
+if test x"$enable_abyss_threads" != xno; then
+    CFLAGS="$CFLAGS -D_THREAD"
+fi
+
+
+
+if test $MUST_BUILD_WININET_CLIENT = yes; then
+
+        for ac_prog in wininet-xmlrpc-config wininet-config
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_WININET_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $WININET_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_WININET_CONFIG="$WININET_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_WININET_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+WININET_CONFIG=$ac_cv_path_WININET_CONFIG
+
+if test -n "$WININET_CONFIG"; then
+  echo "$as_me:$LINENO: result: $WININET_CONFIG" >&5
+echo "${ECHO_T}$WININET_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$WININET_CONFIG" && break
+done
+test -n "$WININET_CONFIG" || WININET_CONFIG="no"
+
+    if test "x$WININET_CONFIG" = "xno"; then
+        { { echo "$as_me:$LINENO: error: wininet lib not found; see './configure --help'" >&5
+echo "$as_me: error: wininet lib not found; see './configure --help'" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+            echo "$as_me:$LINENO: checking for wininet version >= 1.0.0" >&5
+echo $ECHO_N "checking for wininet version >= 1.0.0... $ECHO_C" >&6
+    W3VER=`$WININET_CONFIG --version`
+    WININET_MAJOR=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+    WININET_MINOR=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+    WININET_MICRO=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+    echo "$as_me:$LINENO: result: $WININET_MAJOR.$WININET_MINOR.$WININET_MICRO" >&5
+echo "${ECHO_T}$WININET_MAJOR.$WININET_MINOR.$WININET_MICRO" >&6
+
+        WININET_VERSION_OK=yes
+    if test $WININET_MAJOR -lt 1; then
+        WININET_VERSION_OK=no
+    else
+        if test $WININET_MAJOR -eq 1 -a $WININET_MINOR -lt 0; then
+            WININET_VERSION_OK=no
+        else
+            if test $WININET_MAJOR -eq 1 -a $WININET_MINOR -eq 0 \
+                -a $WININET_MICRO -lt 0; then
+                WININET_VERSION_OK=no
+            fi
+        fi
+    fi
+    if test "x$WININET_VERSION_OK" = "xno"; then
+        { { echo "$as_me:$LINENO: error: wininet version >= 1.0.0 required" >&5
+echo "$as_me: error: wininet version >= 1.0.0 required" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+        WININET_CFLAGS="`$WININET_CONFIG --cflags`"
+
+    CFLAGS="$CFLAGS $WININET_CFLAGS"
+
+        WININET_LDADD="`$WININET_CONFIG --libs`"
+
+
+                echo "$as_me:$LINENO: checking for wininet library directory" >&5
+echo $ECHO_N "checking for wininet library directory... $ECHO_C" >&6
+    if $WININET_CONFIG --rpath-dir > /dev/null 2>&1; then
+              WININET_LIBDIR="`$WININET_CONFIG --rpath-dir`"
+    else
+              WININET_LIBDIR="`$WININET_CONFIG --prefix`/lib"
+    fi
+    echo "$as_me:$LINENO: result: $WININET_LIBDIR" >&5
+echo "${ECHO_T}$WININET_LIBDIR" >&6
+
+    WININET_RPATH="-rpath $WININET_LIBDIR"
+
+    WININET_WL_RPATH="-Wl,--rpath -Wl,$WININET_LIBDIR"
+
+
+fi # MUST_BUILD_WININET_CLIENT
+
+
+if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+
+            for ac_prog in libwww-xmlrpc-config libwww-config
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_LIBWWW_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $LIBWWW_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LIBWWW_CONFIG="$LIBWWW_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LIBWWW_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+LIBWWW_CONFIG=$ac_cv_path_LIBWWW_CONFIG
+
+if test -n "$LIBWWW_CONFIG"; then
+  echo "$as_me:$LINENO: result: $LIBWWW_CONFIG" >&5
+echo "${ECHO_T}$LIBWWW_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$LIBWWW_CONFIG" && break
+done
+test -n "$LIBWWW_CONFIG" || LIBWWW_CONFIG="no"
+
+    if test "x$LIBWWW_CONFIG" = "xno"; then
+        { { echo "$as_me:$LINENO: error: w3c-libwww not found; see './configure --help'" >&5
+echo "$as_me: error: w3c-libwww not found; see './configure --help'" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+            echo "$as_me:$LINENO: checking for w3c-libwww version >= 5.2.8" >&5
+echo $ECHO_N "checking for w3c-libwww version >= 5.2.8... $ECHO_C" >&6
+    W3VER=`$LIBWWW_CONFIG --version`
+    LIBWWW_MAJOR=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+    LIBWWW_MINOR=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+    LIBWWW_MICRO=\
+`echo $W3VER|sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+    echo "$as_me:$LINENO: result: $LIBWWW_MAJOR.$LIBWWW_MINOR.$LIBWWW_MICRO" >&5
+echo "${ECHO_T}$LIBWWW_MAJOR.$LIBWWW_MINOR.$LIBWWW_MICRO" >&6
+
+        LIBWWW_VERSION_OK=yes
+    if test $LIBWWW_MAJOR -lt 5; then
+        LIBWWW_VERSION_OK=no
+    else
+        if test $LIBWWW_MAJOR -eq 5 -a $LIBWWW_MINOR -lt 2; then
+            LIBWWW_VERSION_OK=no
+        else
+            if test $LIBWWW_MAJOR -eq 5 -a $LIBWWW_MINOR -eq 2 \
+                -a $LIBWWW_MICRO -lt 8; then
+                LIBWWW_VERSION_OK=no
+            fi
+        fi
+    fi
+    if test "x$LIBWWW_VERSION_OK" = "xno"; then
+        { { echo "$as_me:$LINENO: error: w3c-libwww version >= 5.2.8 required" >&5
+echo "$as_me: error: w3c-libwww version >= 5.2.8 required" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+        LIBWWW_LDADD="`$LIBWWW_CONFIG --libs`"
+
+
+                echo "$as_me:$LINENO: checking for libwww library directory" >&5
+echo $ECHO_N "checking for libwww library directory... $ECHO_C" >&6
+    if $LIBWWW_CONFIG --rpath-dir > /dev/null 2>&1; then
+              LIBWWW_LIBDIR="`$LIBWWW_CONFIG --rpath-dir`"
+    else
+              LIBWWW_LIBDIR="`$LIBWWW_CONFIG --prefix`/lib"
+    fi
+    echo "$as_me:$LINENO: result: $LIBWWW_LIBDIR" >&5
+echo "${ECHO_T}$LIBWWW_LIBDIR" >&6
+
+
+    # Some ancient rpath stuff, now disabled.  I turned this off because it
+    # breaks Debian (and Mandrake?) policy, and we don't use it anymore.
+    # If you have multiple copies of w3c-libwww lying around, you can turn
+    # it back on.
+    #LIBWWW_RPATH="-rpath $LIBWWW_LIBDIR"
+    LIBWWW_RPATH=""
+
+    #LIBWWW_WL_RPATH="-Wl,--rpath -Wl,$LIBWWW_LIBDIR"
+    LIBWWW_WL_RPATH=""
+
+
+fi # MUST_BUILD_LIBWWW_CLIENT
+
+
+
+if test $MUST_BUILD_CURL_CLIENT = yes; then
+
+            for ac_prog in curl-xmlrpc-config curl-config
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_CURL_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $CURL_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_CURL_CONFIG="$CURL_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_CURL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+CURL_CONFIG=$ac_cv_path_CURL_CONFIG
+
+if test -n "$CURL_CONFIG"; then
+  echo "$as_me:$LINENO: result: $CURL_CONFIG" >&5
+echo "${ECHO_T}$CURL_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$CURL_CONFIG" && break
+done
+test -n "$CURL_CONFIG" || CURL_CONFIG="no"
+
+    if test "x$CURL_CONFIG" = "xno"; then
+        { { echo "$as_me:$LINENO: error: cURL not found; see './configure --help'" >&5
+echo "$as_me: error: cURL not found; see './configure --help'" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+
+                    CURL_LDADD=`$CURL_CONFIG --libs`
+
+
+                echo "$as_me:$LINENO: checking for curl library directory" >&5
+echo $ECHO_N "checking for curl library directory... $ECHO_C" >&6
+        CURL_LIBDIR="`$CURL_CONFIG --prefix`/lib"
+
+    echo "$as_me:$LINENO: result: $CURL_LIBDIR" >&5
+echo "${ECHO_T}$CURL_LIBDIR" >&6
+
+    CURL_RPATH="-rpath $CURL_LIBDIR"
+
+    CURL_WL_RPATH="-Wl,--rpath -Wl,$CURL_LIBDIR"
+
+
+fi # MUST_BUILD_CURL_CLIENT
+
+
+
+
+# Check whether --with-libwww-ssl or --without-libwww-ssl was given.
+if test "${with_libwww_ssl+set}" = set; then
+  withval="$with_libwww_ssl"
+
+fi;
+
+if test x"$enable_libwww_client" != xno; then
+    echo "$as_me:$LINENO: checking whether to use SSL with libwww" >&5
+echo $ECHO_N "checking whether to use SSL with libwww... $ECHO_C" >&6
+    if test x"$with_libwww_ssl" = xyes; then
+        echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+        HAVE_LIBWWW_SSL_DEFINE=1
+    else
+        echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+        HAVE_LIBWWW_SSL_DEFINE=0
+    fi
+fi
+
+
+# Check whether --enable-libxml2-backend or --disable-libxml2-backend was given.
+if test "${enable_libxml2_backend+set}" = set; then
+  enableval="$enable_libxml2_backend"
+
+else
+  enable_libxml2_backend=no
+fi;
+echo "$as_me:$LINENO: checking whether to build the libxml2 backend" >&5
+echo $ECHO_N "checking whether to build the libxml2 backend... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $enable_libxml2_backend" >&5
+echo "${ECHO_T}$enable_libxml2_backend" >&6
+
+if test $enable_libxml2_backend = yes; then
+  # Extract the first word of "xml2-config", so it can be a program name with args.
+set dummy xml2-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_have_xml2_config+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$have_xml2_config"; then
+  ac_cv_prog_have_xml2_config="$have_xml2_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_xml2_config="yes"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_have_xml2_config" && ac_cv_prog_have_xml2_config="no"
+fi
+fi
+have_xml2_config=$ac_cv_prog_have_xml2_config
+if test -n "$have_xml2_config"; then
+  echo "$as_me:$LINENO: result: $have_xml2_config" >&5
+echo "${ECHO_T}$have_xml2_config" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  if test $have_xml2_config = no; then
+    { { echo "$as_me:$LINENO: error: You specified --enable-libxml2_backend, but don't appear to have libxml2 installed (no working xml2-config inyour command search path), so we cannot not build for libxml2" >&5
+echo "$as_me: error: You specified --enable-libxml2_backend, but don't appear to have libxml2 installed (no working xml2-config inyour command search path), so we cannot not build for libxml2" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+ENABLE_LIBXML2_BACKEND=$enable_libxml2_backend
+
+
+C_COMPILER_GNU=$ac_cv_c_compiler_gnu
+
+CXX_COMPILER_GNU=$ac_cv_cxx_compiler_gnu
+
+
+CC_WARN_FLAGS=
+
+CPP_WARN_FLAGS=
+
+
+
+BUILDDIR=`pwd`
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval="$enable_shared"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_shared=yes
+fi;
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval="$enable_static"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_static=yes
+fi;
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval="$enable_fast_install"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_fast_install=yes
+fi;
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$ac_cv_c_compiler_gnu" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6
+  ac_prog=`($CC -print-prog-name=ld) 2>&5`
+  case "$ac_prog" in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${ac_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      ac_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+  echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${ac_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  ac_cv_prog_gnu_ld=yes
+else
+  ac_cv_prog_gnu_ld=no
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$ac_cv_prog_gnu_ld" >&6
+
+
+echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
+if test "${ac_cv_path_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  ac_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -B"
+       break
+      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -p"
+       break
+      else
+       ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi
+fi
+
+NM="$ac_cv_path_NM"
+echo "$as_me:$LINENO: result: $NM" >&5
+echo "${ECHO_T}$NM" >&6
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+
+case "$target" in
+NONE) lt_target="$host" ;;
+*) lt_target="$target" ;;
+esac
+
+# Check for any special flags to pass to ltconfig.
+#
+# the following will cause an existing older ltconfig to fail, so
+# we ignore this at the expense of the cache file... Checking this
+# will just take longer ... bummer!
+#libtool_flags="--cache-file=$cache_file"
+#
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$ac_cv_c_compiler_gnu" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
+test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$lt_target" in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 6049 "configure"' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  lt_cv_cc_needs_belf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+lt_cv_cc_needs_belf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+
+esac
+
+
+# Save cache, so that ltconfig can load it
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
+LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
+DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \
+|| { { echo "$as_me:$LINENO: error: libtool configure failed" >&5
+echo "$as_me: error: libtool configure failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+# Reload cache, that may have been modified by ltconfig
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+
+
+
+
+
+                                        ac_config_files="$ac_config_files xmlrpc-c-config xmlrpc-c-config.test Makefile.config xmlrpc_config.h"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[    ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[      ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                  instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                  instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "xmlrpc-c-config" ) CONFIG_FILES="$CONFIG_FILES xmlrpc-c-config" ;;
+  "xmlrpc-c-config.test" ) CONFIG_FILES="$CONFIG_FILES xmlrpc-c-config.test" ;;
+  "Makefile.config" ) CONFIG_FILES="$CONFIG_FILES Makefile.config" ;;
+  "xmlrpc_config.h" ) CONFIG_FILES="$CONFIG_FILES xmlrpc_config.h" ;;
+  "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+  "xmlrpc_amconfig.h" ) CONFIG_HEADERS="$CONFIG_HEADERS xmlrpc_amconfig.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOMAKE@,$AUTOMAKE,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@VERSION_INFO@,$VERSION_INFO,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@have_wininet_config@,$have_wininet_config,;t t
+s,@MUST_BUILD_WININET_CLIENT@,$MUST_BUILD_WININET_CLIENT,;t t
+s,@have_curl_config@,$have_curl_config,;t t
+s,@MUST_BUILD_CURL_CLIENT@,$MUST_BUILD_CURL_CLIENT,;t t
+s,@have_libwww_config@,$have_libwww_config,;t t
+s,@MUST_BUILD_LIBWWW_CLIENT@,$MUST_BUILD_LIBWWW_CLIENT,;t t
+s,@LIBXMLRPC_CLIENT_LA@,$LIBXMLRPC_CLIENT_LA,;t t
+s,@CLIENTTEST@,$CLIENTTEST,;t t
+s,@XMLRPC_CLIENT_H@,$XMLRPC_CLIENT_H,;t t
+s,@XMLRPC_TRANSPORT_H@,$XMLRPC_TRANSPORT_H,;t t
+s,@SYNCH_CLIENT@,$SYNCH_CLIENT,;t t
+s,@ASYNCH_CLIENT@,$ASYNCH_CLIENT,;t t
+s,@AUTH_CLIENT@,$AUTH_CLIENT,;t t
+s,@QUERY_MEERKAT@,$QUERY_MEERKAT,;t t
+s,@ENABLE_ABYSS_SERVER@,$ENABLE_ABYSS_SERVER,;t t
+s,@ABYSS_SUBDIR@,$ABYSS_SUBDIR,;t t
+s,@LIBXMLRPC_ABYSS_SERVER_LA@,$LIBXMLRPC_ABYSS_SERVER_LA,;t t
+s,@SERVERTEST@,$SERVERTEST,;t t
+s,@VALIDATEE@,$VALIDATEE,;t t
+s,@XMLRPC_ABYSS_H@,$XMLRPC_ABYSS_H,;t t
+s,@SERVER@,$SERVER,;t t
+s,@ENABLE_CGI_SERVER@,$ENABLE_CGI_SERVER,;t t
+s,@ENABLE_CPLUSPLUS@,$ENABLE_CPLUSPLUS,;t t
+s,@LIBXMLRPC_CPP_A@,$LIBXMLRPC_CPP_A,;t t
+s,@CPPTEST@,$CPPTEST,;t t
+s,@XMLRPCCPP_H@,$XMLRPCCPP_H,;t t
+s,@XML_RPC_API2CPP_SUBDIR@,$XML_RPC_API2CPP_SUBDIR,;t t
+s,@FEATURE_LIST@,$FEATURE_LIST,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@LSOCKET@,$LSOCKET,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@HAVE_WCHAR_H_DEFINE@,$HAVE_WCHAR_H_DEFINE,;t t
+s,@HAVE_SYS_FILIO_H_DEFINE@,$HAVE_SYS_FILIO_H_DEFINE,;t t
+s,@HAVE_SYS_IOCTL_H_DEFINE@,$HAVE_SYS_IOCTL_H_DEFINE,;t t
+s,@VA_LIST_IS_ARRAY_DEFINE@,$VA_LIST_IS_ARRAY_DEFINE,;t t
+s,@ATTR_UNUSED@,$ATTR_UNUSED,;t t
+s,@DIRECTORY_SEPARATOR@,$DIRECTORY_SEPARATOR,;t t
+s,@ENABLE_ABYSS_THREADS@,$ENABLE_ABYSS_THREADS,;t t
+s,@WININET_CONFIG@,$WININET_CONFIG,;t t
+s,@WININET_CFLAGS@,$WININET_CFLAGS,;t t
+s,@WININET_LDADD@,$WININET_LDADD,;t t
+s,@WININET_LIBDIR@,$WININET_LIBDIR,;t t
+s,@WININET_RPATH@,$WININET_RPATH,;t t
+s,@WININET_WL_RPATH@,$WININET_WL_RPATH,;t t
+s,@LIBWWW_CONFIG@,$LIBWWW_CONFIG,;t t
+s,@LIBWWW_LDADD@,$LIBWWW_LDADD,;t t
+s,@LIBWWW_LIBDIR@,$LIBWWW_LIBDIR,;t t
+s,@LIBWWW_RPATH@,$LIBWWW_RPATH,;t t
+s,@LIBWWW_WL_RPATH@,$LIBWWW_WL_RPATH,;t t
+s,@CURL_CONFIG@,$CURL_CONFIG,;t t
+s,@CURL_LDADD@,$CURL_LDADD,;t t
+s,@CURL_LIBDIR@,$CURL_LIBDIR,;t t
+s,@CURL_RPATH@,$CURL_RPATH,;t t
+s,@CURL_WL_RPATH@,$CURL_WL_RPATH,;t t
+s,@HAVE_LIBWWW_SSL_DEFINE@,$HAVE_LIBWWW_SSL_DEFINE,;t t
+s,@have_xml2_config@,$have_xml2_config,;t t
+s,@ENABLE_LIBXML2_BACKEND@,$ENABLE_LIBXML2_BACKEND,;t t
+s,@C_COMPILER_GNU@,$C_COMPILER_GNU,;t t
+s,@CXX_COMPILER_GNU@,$CXX_COMPILER_GNU,;t t
+s,@CC_WARN_FLAGS@,$CC_WARN_FLAGS,;t t
+s,@CPP_WARN_FLAGS@,$CPP_WARN_FLAGS,;t t
+s,@BUILDDIR@,$BUILDDIR,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@LN_S@,$LN_S,;t t
+s,@LIBTOOL@,$LIBTOOL,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                    sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([   ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='[        ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([   ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        # Do quote $f, to prevent DOS paths from being IFS'd.
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[      ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*\)\(([^)]*)\)[       ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[    ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[     ]*#[    ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[     ]*#[    ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[     ]*#[    ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+  ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_dest" : 'X\(//\)[^/]' \| \
+        X"$ac_dest" : 'X\(//\)$' \| \
+        X"$ac_dest" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+  case $ac_dest in
+    default-1 ) test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h ;;
+  esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+chmod +x xmlrpc-c-config
+chmod +x xmlrpc-c-config.test
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..092a2d7
--- /dev/null
@@ -0,0 +1,650 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(include/xmlrpc-c/base.h)
+AM_CONFIG_HEADER(xmlrpc_amconfig.h)
+
+dnl =======================================================================
+dnl Define PACKAGE, VERSION, @PACKAGE@, @VERSION@
+dnl =======================================================================
+
+dnl Increment the package version for each release.
+AM_INIT_AUTOMAKE(xmlrpc-c, 1.06.32)
+
+dnl This version number needs to be changed in several *different* tricky
+dnl ways for each release. Please read the libtool documentation very
+dnl closely before touching this or making a release!
+VERSION_INFO="-version-info 7:0:6"
+AC_SUBST(VERSION_INFO)
+
+dnl Define @build@, @build_cpu@, @build_vendor@, @build_os,
+dnl @host, @host_cpu@, @host_vender, and @host_os@ substitutions.
+dnl "host" means the target system -- the one for which we are building.
+dnl "build" means the system that will do the building.
+AC_CANONICAL_HOST
+
+dnl We need this to compensate for an incompatibility between autoconf
+dnl and our libtool.  autoconf generates an invalid ltconfig command
+dnl otherwise.
+test -z "$target" && target=NONE
+
+dnl =======================================================================
+dnl Decide What To Build
+dnl =======================================================================
+
+FEATURE_LIST=
+
+AC_ARG_ENABLE(wininet-client,
+  [  --disable-wininet-client  Don't build the Wininet client transport], , 
+enable_wininet_client=maybe)
+
+if test $enable_wininet_client = maybe; then
+  AC_CHECK_PROG(have_wininet_config, wininet-config, yes, no)
+  if test $have_wininet_config = no; then
+    AC_MSG_NOTICE([You don't appear to have Wininet installed (no working wininet-config in your command search path), so we will not build the Wininet client XML transport])
+    MUST_BUILD_WININET_CLIENT=no
+  else
+    MUST_BUILD_WININET_CLIENT=yes
+  fi
+else
+  MUST_BUILD_WININET_CLIENT=$enable_wininet_client
+fi
+
+AC_MSG_CHECKING(whether to build Wininet client XML transport module)
+AC_MSG_RESULT($MUST_BUILD_WININET_CLIENT)
+AC_SUBST(MUST_BUILD_WININET_CLIENT)
+
+
+AC_ARG_ENABLE(curl-client,
+  [  --disable-curl-client     Don't build the Curl client transport], , 
+enable_curl_client=maybe)
+
+if test $enable_curl_client = maybe; then
+  AC_CHECK_PROG(have_curl_config, curl-config, yes, no)
+  if test $have_curl_config = no; then
+    AC_MSG_NOTICE([You don't appear to have Curl installed (no working curl-config in your command search path), so we will not build the Curl client XML transport])
+    MUST_BUILD_CURL_CLIENT=no
+  else
+    MUST_BUILD_CURL_CLIENT=yes
+  fi
+else
+  MUST_BUILD_CURL_CLIENT=$enable_curl_client
+fi
+
+AC_MSG_CHECKING(whether to build Curl client XML transport module)
+AC_MSG_RESULT($MUST_BUILD_CURL_CLIENT)
+AC_SUBST(MUST_BUILD_CURL_CLIENT)
+
+
+AC_ARG_ENABLE(libwww-client,
+  [  --disable-libwww-client   Don't build the Libwww client transport], , 
+enable_libwww_client=maybe)
+
+if test $enable_libwww_client = maybe; then
+  AC_CHECK_PROG(have_libwww_config, libwww-config, yes, no)
+  if test $have_libwww_config = no; then
+    AC_MSG_NOTICE([You don't appear to have Libwww installed (no working libwww-config in your command search path), so we will not build the Libwww client XML transport])
+    MUST_BUILD_LIBWWW_CLIENT=no
+  else
+    MUST_BUILD_LIBWWW_CLIENT=yes
+  fi
+else
+  MUST_BUILD_LIBWWW_CLIENT=$enable_libwww_client
+fi
+
+AC_MSG_CHECKING(whether to build Libwww client XML transport module)
+AC_MSG_RESULT($MUST_BUILD_LIBWWW_CLIENT)
+AC_SUBST(MUST_BUILD_LIBWWW_CLIENT)
+
+
+if test "$MUST_BUILD_WININET_CLIENT $MUST_BUILD_CURL_CLIENT $MUST_BUILD_LIBWWW_CLIENT" = "no no no"; then
+  AC_MSG_NOTICE([We are not building any client XML transport, therefore we will not build the client library at all.])
+fi
+
+
+dnl Set up the appropriate Makefile substitutions.
+
+LIBXMLRPC_CLIENT_LA=libxmlrpc_client.la
+AC_SUBST(LIBXMLRPC_CLIENT_LA)
+CLIENTTEST=clienttest
+AC_SUBST(CLIENTTEST)
+XMLRPC_CLIENT_H=xmlrpc_client.h
+AC_SUBST(XMLRPC_CLIENT_H)
+XMLRPC_TRANSPORT_H=xmlrpc_transport.h
+AC_SUBST(XMLRPC_TRANSPORT_H)
+SYNCH_CLIENT=synch_client
+AC_SUBST(SYNCH_CLIENT)
+ASYNCH_CLIENT=asynch_client
+AC_SUBST(ASYNCH_CLIENT)
+AUTH_CLIENT=auth_client
+AC_SUBST(AUTH_CLIENT)
+QUERY_MEERKAT=query-meerkat
+AC_SUBST(QUERY_MEERKAT)
+
+if test $MUST_BUILD_WININET_CLIENT = yes; then
+    FEATURE_LIST="wininet-client $FEATURE_LIST"
+fi
+if test $MUST_BUILD_CURL_CLIENT = yes; then
+    FEATURE_LIST="curl-client $FEATURE_LIST"
+fi
+if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+    FEATURE_LIST="libwww-client $FEATURE_LIST"
+fi
+
+dnl Check to see if we should build our Abyss server module.
+AC_MSG_CHECKING(whether to build Abyss server module)
+AC_ARG_ENABLE(abyss-server,
+  [  --disable-abyss-server    Don't build the Abyss server module], ,
+enable_abyss_server=yes)
+AC_MSG_RESULT($enable_abyss_server)
+ENABLE_ABYSS_SERVER=$enable_abyss_server
+AC_SUBST(ENABLE_ABYSS_SERVER)
+
+dnl Set up the appropriate Makefile substitutions.
+ABYSS_SUBDIR=
+LIBXMLRPC_ABYSS_SERVER_LA=
+SERVERTEST=
+VALIDATEE=
+XMLRPC_ABYSS_H=
+SERVER=
+if test x"$enable_abyss_server" != xno; then
+    FEATURE_LIST="abyss-server $FEATURE_LIST"
+    ABYSS_SUBDIR=abyss
+    LIBXMLRPC_ABYSS_SERVER_LA=libxmlrpc_abyss_server.la
+    SERVERTEST=servertest
+    VALIDATEE=validatee
+    XMLRPC_ABYSS_H=xmlrpc_abyss.h
+    SERVER=server
+fi
+AC_SUBST(ABYSS_SUBDIR)
+AC_SUBST(LIBXMLRPC_ABYSS_SERVER_LA)
+AC_SUBST(SERVERTEST)
+AC_SUBST(VALIDATEE)
+AC_SUBST(XMLRPC_ABYSS_H)
+AC_SUBST(SERVER)
+
+dnl Check to see if we should build our CGI server module.
+AC_MSG_CHECKING(whether to build CGI server module)
+AC_ARG_ENABLE(cgi-server,
+  [  --disable-cgi-server      Don't build the CGI server module], ,
+enable_cgi_server=yes)
+AC_MSG_RESULT($enable_cgi_server)
+ENABLE_CGI_SERVER=$enable_cgi_server
+AC_SUBST(ENABLE_CGI_SERVER)
+
+dnl Check to see if we should build our C++ stuff.
+AC_MSG_CHECKING(whether to build C++ wrappers and tools)
+AC_ARG_ENABLE(cplusplus,
+  [  --disable-cplusplus       Don't build the C++ wrapper classes or tools], ,
+enable_cplusplus=yes)
+AC_MSG_RESULT($enable_cplusplus)
+ENABLE_CPLUSPLUS=$enable_cplusplus
+AC_SUBST(ENABLE_CPLUSPLUS)
+
+dnl Set up the appropriate Makefile substitutions.
+LIBXMLRPC_CPP_A=
+CPPTEST=
+XMLRPCCPP_H=
+XML_RPC_API2CPP_SUBDIR=
+MEERKAT_APP_LIST=
+INTEROP_CLIENT_SUBDIR=
+if test x"$enable_cplusplus" != xno; then
+    FEATURE_LIST="c++ $FEATURE_LIST"
+    LIBXMLRPC_CPP_A=libxmlrpc_cpp.a
+    CPPTEST=cpptest
+    XMLRPCCPP_H=XmlRpcCpp.h
+
+    if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+        XML_RPC_API2CPP_SUBDIR=xml-rpc-api2cpp
+    elif test $MUST_BUILD_CURL_CLIENT = yes; then
+        XML_RPC_API2CPP_SUBDIR=xml-rpc-api2cpp
+    fi
+fi
+AC_SUBST(LIBXMLRPC_CPP_A)
+AC_SUBST(CPPTEST)
+AC_SUBST(XMLRPCCPP_H)
+AC_SUBST(XML_RPC_API2CPP_SUBDIR)
+
+
+AC_SUBST(FEATURE_LIST)
+
+
+dnl =======================================================================
+dnl Checks for programs.
+dnl =======================================================================
+
+AC_PROG_CC
+if test x"$enable_cplusplus" != xno; then
+    AC_PROG_CXX
+fi
+
+
+dnl =======================================================================
+dnl Checks for libraries.
+dnl =======================================================================
+
+# Code by albert chin <china@thewrittenword.com> to check for various
+# oddball networking libraries.  Solaris and some other operating systems
+# hide their networking code in various places.  (Yes, this links too many
+# of our libraries against -lsocket, but a finer-grained mechanism would
+# require too much testing.)
+AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket))
+
+# Above sets LIBS, which is not all that useful because we don't want
+# to include every library in every link.  It also sets
+# ac_cv_lib_socket_socket, which we use to pass more specific information
+# to the configuration files.
+
+if test x"$ac_cv_lib_socket_socket" = xyes; then
+  LSOCKET=-lsocket
+else
+  LSOCKET=
+fi
+AC_SUBST(LSOCKET)
+
+# For some reason, we don't seem to need this on Solaris.  If you do
+# need it, go ahead and try it.
+# AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent))
+
+
+dnl =======================================================================
+dnl Checks for header files.
+dnl =======================================================================
+
+AC_STDC_HEADERS
+
+dnl We don't use AM_CONFIG_HEADER to define HAVE_WCHAR_H, etc. because
+dnl the following is more straightforward and easier to understand,
+dnl especially for a newcomer.  Furthermore, AM_CONFIG_HEADER represents
+dnl false as undefined, whereas our scheme represents it as 0.  undefined
+dnl is a poor choice because it often means just that you neglected to
+dnl choose a value for some reason.
+
+dnl defines ac_cv_header_wchar_h, etc:
+AC_CHECK_HEADERS(wchar.h)
+
+if test x"$ac_cv_header_wchar_h" = xyes; then
+  HAVE_WCHAR_H_DEFINE=1
+else
+  HAVE_WCHAR_H_DEFINE=0
+fi
+AC_SUBST(HAVE_WCHAR_H_DEFINE)
+
+# Needed by Abyss on Solaris:
+
+AC_CHECK_HEADERS(sys/filio.h)
+if test x"$ac_cv_header_sys_filio_h" = xyes; then
+  HAVE_SYS_FILIO_H_DEFINE=1
+else
+  HAVE_SYS_FILIO_H_DEFINE=0
+fi
+AC_SUBST(HAVE_SYS_FILIO_H_DEFINE)
+
+# Needed by Abyss on Solaris:
+
+AC_CHECK_HEADERS(sys/ioctl.h)
+if test x"$ac_cv_header_sys_ioctl_h" = xyes; then
+  HAVE_SYS_IOCTL_H_DEFINE=1
+else
+  HAVE_SYS_IOCTL_H_DEFINE=0
+fi
+AC_SUBST(HAVE_SYS_IOCTL_H_DEFINE)
+
+
+AC_CHECK_HEADERS(stdarg.h, , [
+AC_MSG_ERROR(stdarg.h is required to build this library)
+])
+
+
+dnl =======================================================================
+dnl Checks for typedefs, structures, and compiler characteristics.
+dnl =======================================================================
+
+dnl AC_C_BIGENDIAN
+AC_TYPE_SIZE_T
+
+dnl This check is borrowed from Python 1.5.2.
+va_list_is_array=no
+AC_MSG_CHECKING(whether va_list is an array)
+AC_TRY_COMPILE([
+#include <stdarg.h>
+], [va_list list1, list2; list1 = list2;], , 
+va_list_is_array=yes)
+AC_MSG_RESULT($va_list_is_array)
+if test x"$va_list_is_array" = xyes; then
+  VA_LIST_IS_ARRAY_DEFINE=1
+else
+  VA_LIST_IS_ARRAY_DEFINE=0
+fi
+AC_SUBST(VA_LIST_IS_ARRAY_DEFINE)
+
+AC_MSG_CHECKING(whether compiler has __attribute__)
+AC_TRY_COMPILE(, [int x __attribute__((__unused__));],
+compiler_has_attribute=yes,
+compiler_has_attribute=no)
+AC_MSG_RESULT($compiler_has_attribute)
+if test x"$compiler_has_attribute" = xyes; then
+    ATTR_UNUSED="__attribute__((__unused__))"
+else
+    ATTR_UNUSED=
+fi
+AC_SUBST(ATTR_UNUSED)
+
+
+dnl =======================================================================
+dnl Checks for library functions.
+dnl =======================================================================
+
+AC_CHECK_FUNC(vsnprintf, , [
+AC_MSG_ERROR(your C library does not provide vsnprintf)
+])
+
+dnl Unicode function needed by test suites.
+AC_CHECK_FUNCS(wcsncmp)
+
+dnl CygWin looks like Unix, but doesn't provide setgroups.
+AC_CHECK_FUNCS(setgroups)
+
+AC_CHECK_FUNCS(asprintf)
+
+AC_CHECK_FUNCS(setenv)
+
+
+dnl =======================================================================
+dnl Checks for operating system features.
+dnl =======================================================================
+
+dnl Non-Unix systems will need to set up their platform configuration file
+dnl by hand.
+DIRECTORY_SEPARATOR="/"
+AC_SUBST(DIRECTORY_SEPARATOR)
+
+
+dnl =======================================================================
+dnl ABYSS Configuration
+dnl =======================================================================
+
+AC_MSG_CHECKING(whether to use Abyss pthread function)
+AC_ARG_ENABLE(abyss-threads,
+  [  --disable-abyss-threads   Use fork in Abyss instead of pthreads], ,
+  enable_abyss_threads=yes)
+AC_MSG_RESULT($enable_abyss_threads)
+
+ENABLE_ABYSS_THREADS=$enable_abyss_threads
+AC_SUBST(ENABLE_ABYSS_THREADS)
+
+if test x"$enable_abyss_threads" != xno; then
+    CFLAGS="$CFLAGS -D_THREAD"
+fi
+
+
+dnl =======================================================================
+dnl Finding wininet stubs
+dnl =======================================================================
+dnl If you implement the parts of wininet.h the wininet_transport uses,
+dnl you will need to configure this way..
+
+if test $MUST_BUILD_WININET_CLIENT = yes; then
+
+    dnl You can control which of these gets chosen by fooling around with PATH.
+    AC_PATH_PROGS(WININET_CONFIG, wininet-xmlrpc-config wininet-config, no)
+    if test "x$WININET_CONFIG" = "xno"; then
+        AC_MSG_ERROR(wininet lib not found; see './configure --help')
+    fi
+
+    dnl Get our wininet version.
+    dnl Adapted from a macro which called gtk-config.
+    AC_MSG_CHECKING(for wininet version >= 1.0.0)
+    W3VER=`$WININET_CONFIG --version`
+    WININET_MAJOR=\
+`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
+    WININET_MINOR=\
+`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
+    WININET_MICRO=\
+`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
+    AC_MSG_RESULT($WININET_MAJOR.$WININET_MINOR.$WININET_MICRO)
+
+    dnl Check to make sure our version is OK.
+    WININET_VERSION_OK=yes
+    if test $WININET_MAJOR -lt 1; then
+        WININET_VERSION_OK=no
+    else
+        if test $WININET_MAJOR -eq 1 -a $WININET_MINOR -lt 0; then
+            WININET_VERSION_OK=no
+        else
+            if test $WININET_MAJOR -eq 1 -a $WININET_MINOR -eq 0 \
+                -a $WININET_MICRO -lt 0; then
+                WININET_VERSION_OK=no
+            fi
+        fi
+    fi
+    if test "x$WININET_VERSION_OK" = "xno"; then
+        AC_MSG_ERROR(wininet version >= 1.0.0 required)
+    fi
+
+    dnl Get the necessary CFLAGS, and merge them into our master list.
+    WININET_CFLAGS="`$WININET_CONFIG --cflags`"
+    AC_SUBST(WININET_CFLAGS)
+    CFLAGS="$CFLAGS $WININET_CFLAGS" 
+
+    dnl Get the huge list of libraries we need to link against.
+    WININET_LDADD="`$WININET_CONFIG --libs`"
+    AC_SUBST(WININET_LDADD)
+
+    dnl Oh, such massive brain damage! Because there may be another copy
+    dnl of libwww in the default dynamic loader search path, we need to
+    dnl adjust the search patch manually. Just gag me with a backquote, OK?
+    AC_MSG_CHECKING(for wininet library directory)
+    if $WININET_CONFIG --rpath-dir > /dev/null 2>&1; then
+       dnl Yay! We're using our smart version of wininet.
+       WININET_LIBDIR="`$WININET_CONFIG --rpath-dir`"
+    else
+       dnl Yawn. We're using the regular boring version.
+       WININET_LIBDIR="`$WININET_CONFIG --prefix`/lib"
+    fi
+    AC_MSG_RESULT($WININET_LIBDIR)
+    AC_SUBST(WININET_LIBDIR)
+    WININET_RPATH="-rpath $WININET_LIBDIR"
+    AC_SUBST(WININET_RPATH)
+    WININET_WL_RPATH="-Wl,--rpath -Wl,$WININET_LIBDIR"
+    AC_SUBST(WININET_WL_RPATH)
+
+fi # MUST_BUILD_WININET_CLIENT
+
+dnl =======================================================================
+dnl Finding w3c-libwww
+dnl =======================================================================
+dnl Once upon a time, we used a patched copy of libwww that needed to
+dnl co-exist with the system copy of libwww. We have some vestigal function
+dnl for keeping track of libwww's rpath, although this is no longer really
+dnl necessary.
+
+if test $MUST_BUILD_LIBWWW_CLIENT = yes; then
+
+    dnl First of all, locate the semi-broken libwww config program.
+    dnl You can control which of these gets chosen by fooling around with PATH.
+    AC_PATH_PROGS(LIBWWW_CONFIG, libwww-xmlrpc-config libwww-config, no)
+    if test "x$LIBWWW_CONFIG" = "xno"; then
+        AC_MSG_ERROR(w3c-libwww not found; see './configure --help')
+    fi
+
+    dnl Get our libwww version.
+    dnl Adapted from a macro which called gtk-config.
+    AC_MSG_CHECKING(for w3c-libwww version >= 5.2.8)
+    W3VER=`$LIBWWW_CONFIG --version`
+    LIBWWW_MAJOR=\
+`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
+    LIBWWW_MINOR=\
+`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
+    LIBWWW_MICRO=\
+`echo $W3VER|sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
+    AC_MSG_RESULT($LIBWWW_MAJOR.$LIBWWW_MINOR.$LIBWWW_MICRO)
+
+    dnl Check to make sure our version is OK.
+    LIBWWW_VERSION_OK=yes
+    if test $LIBWWW_MAJOR -lt 5; then
+        LIBWWW_VERSION_OK=no
+    else
+        if test $LIBWWW_MAJOR -eq 5 -a $LIBWWW_MINOR -lt 2; then
+            LIBWWW_VERSION_OK=no
+        else
+            if test $LIBWWW_MAJOR -eq 5 -a $LIBWWW_MINOR -eq 2 \
+                -a $LIBWWW_MICRO -lt 8; then
+                LIBWWW_VERSION_OK=no
+            fi
+        fi
+    fi
+    if test "x$LIBWWW_VERSION_OK" = "xno"; then
+        AC_MSG_ERROR(w3c-libwww version >= 5.2.8 required)
+    fi
+
+    dnl Get the huge list of libraries we need to link against.
+    LIBWWW_LDADD="`$LIBWWW_CONFIG --libs`"
+    AC_SUBST(LIBWWW_LDADD)
+
+    dnl Oh, such massive brain damage! Because there may be another copy
+    dnl of libwww in the default dynamic loader search path, we need to
+    dnl adjust the search patch manually. Just gag me with a backquote, OK?
+    AC_MSG_CHECKING(for libwww library directory)
+    if $LIBWWW_CONFIG --rpath-dir > /dev/null 2>&1; then
+       dnl Yay! We're using our smart version of libwww.
+       LIBWWW_LIBDIR="`$LIBWWW_CONFIG --rpath-dir`"
+    else
+       dnl Yawn. We're using the regular boring version.
+       LIBWWW_LIBDIR="`$LIBWWW_CONFIG --prefix`/lib"
+    fi
+    AC_MSG_RESULT($LIBWWW_LIBDIR)
+    AC_SUBST(LIBWWW_LIBDIR)
+
+    # Some ancient rpath stuff, now disabled.  I turned this off because it
+    # breaks Debian (and Mandrake?) policy, and we don't use it anymore.
+    # If you have multiple copies of w3c-libwww lying around, you can turn
+    # it back on.
+    #LIBWWW_RPATH="-rpath $LIBWWW_LIBDIR"
+    LIBWWW_RPATH=""
+    AC_SUBST(LIBWWW_RPATH)
+    #LIBWWW_WL_RPATH="-Wl,--rpath -Wl,$LIBWWW_LIBDIR"
+    LIBWWW_WL_RPATH=""
+    AC_SUBST(LIBWWW_WL_RPATH)
+
+fi # MUST_BUILD_LIBWWW_CLIENT
+
+
+dnl =======================================================================
+dnl Finding cURL
+dnl =======================================================================
+
+if test $MUST_BUILD_CURL_CLIENT = yes; then
+
+    dnl First of all, locate the curl config program.
+    dnl You can control which of these gets chosen by fooling around with PATH.
+    AC_PATH_PROGS(CURL_CONFIG, curl-xmlrpc-config curl-config, no)
+    if test "x$CURL_CONFIG" = "xno"; then
+        AC_MSG_ERROR(cURL not found; see './configure --help')
+    fi
+    
+    dnl There used to be code here to check the Curl version and make sure
+    dnl it is at least 7.8.  But there were bugs both in the code and in 
+    dnl curl (curl-config --vernum, at least in older versios of Curl,
+    dnl omits the leading zero).  So it didn't work.  Plus, checking version
+    dnl numbers isn't a good idea.  Better to check for feature presence.
+    dnl So we don't do any check now.  If we find out there's a problem with
+    dnl older Curls, we will revisit that.
+
+    dnl Get the huge list of libraries we need to link against.
+    dnl MRB-20010516-For some reason, curl-config
+    dnl does not list itself '-lcurl'.  2004.12.12.  It seems to do so
+    dnl now.
+    CURL_LDADD=`$CURL_CONFIG --libs`
+    AC_SUBST(CURL_LDADD)
+
+    dnl Oh, such massive brain damage! Because there may be another copy
+    dnl of curl in the default dynamic loader search path, we need to
+    dnl adjust the search patch manually. Just gag me with a backquote, OK?
+    AC_MSG_CHECKING(for curl library directory)
+    dnl Yawn. We're using the regular boring version.
+    CURL_LIBDIR="`$CURL_CONFIG --prefix`/lib"
+
+    AC_MSG_RESULT($CURL_LIBDIR)
+    AC_SUBST(CURL_LIBDIR)
+    CURL_RPATH="-rpath $CURL_LIBDIR"
+    AC_SUBST(CURL_RPATH)
+    CURL_WL_RPATH="-Wl,--rpath -Wl,$CURL_LIBDIR"
+    AC_SUBST(CURL_WL_RPATH)
+
+fi # MUST_BUILD_CURL_CLIENT
+
+
+dnl =======================================================================
+dnl Checks for build options.
+dnl =======================================================================
+
+AC_ARG_WITH(libwww-ssl,
+  [  --with-libwww-ssl       Include libwww SSL capability.]
+   ) 
+
+if test x"$enable_libwww_client" != xno; then
+    AC_MSG_CHECKING(whether to use SSL with libwww)
+    if test x"$with_libwww_ssl" = xyes; then
+        AC_MSG_RESULT(yes)
+        HAVE_LIBWWW_SSL_DEFINE=1
+    else
+        AC_MSG_RESULT(no)
+        HAVE_LIBWWW_SSL_DEFINE=0
+    fi
+fi
+AC_SUBST(HAVE_LIBWWW_SSL_DEFINE)
+
+dnl Check to see if we should build the libxml2 backend.
+AC_ARG_ENABLE(libxml2-backend,
+  [  --enable-libxml2-backend  Use libxml2 instead of built-in expat], ,
+enable_libxml2_backend=no)
+AC_MSG_CHECKING(whether to build the libxml2 backend)
+AC_MSG_RESULT($enable_libxml2_backend)
+
+if test $enable_libxml2_backend = yes; then
+  AC_CHECK_PROG(have_xml2_config, xml2-config, yes, no)
+  if test $have_xml2_config = no; then
+    AC_MSG_ERROR([You specified --enable-libxml2_backend, but don't appear to have libxml2 installed (no working xml2-config inyour command search path), so we cannot not build for libxml2])
+  fi
+fi
+ENABLE_LIBXML2_BACKEND=$enable_libxml2_backend
+AC_SUBST(ENABLE_LIBXML2_BACKEND)
+
+dnl =======================================================================
+dnl Compiler information
+dnl =======================================================================
+C_COMPILER_GNU=$ac_cv_c_compiler_gnu
+AC_SUBST(C_COMPILER_GNU)
+CXX_COMPILER_GNU=$ac_cv_cxx_compiler_gnu
+AC_SUBST(CXX_COMPILER_GNU)
+
+dnl obsolete variables, need to be removed from Makefile.in:
+CC_WARN_FLAGS=
+AC_SUBST(CC_WARN_FLAGS)
+CPP_WARN_FLAGS=
+AC_SUBST(CPP_WARN_FLAGS)
+
+
+BUILDDIR=`pwd`
+AC_SUBST(BUILDDIR)
+
+dnl =======================================================================
+dnl Libtool
+dnl =======================================================================
+AM_PROG_LIBTOOL
+
+
+dnl =======================================================================
+dnl Output our results.
+dnl =======================================================================
+
+dnl Note that AM_CONFIG_HEADER at the top of this file outputs another
+dnl result: xmlrpc_amconfig.h .
+
+AC_OUTPUT(xmlrpc-c-config \
+          xmlrpc-c-config.test \
+          Makefile.config \
+          xmlrpc_config.h \
+          )
+chmod +x xmlrpc-c-config
+chmod +x xmlrpc-c-config.test
diff --git a/doc/COPYING b/doc/COPYING
new file mode 100644 (file)
index 0000000..1d83762
--- /dev/null
@@ -0,0 +1,143 @@
+The copyright owners of this package license the public to copy it
+(and do other things with it which are controlled by copyright law)
+under a few simple conditions.
+
+Each source files describes the copyright license for that particular
+file.  This file summarizes the licenses for your convenience.
+
+All the code written specifically for Xmlrpc-c, which is most
+of the code, and the aggregation, is licensed under the
+XML-RPC FOR C/C++ license shown below.
+
+Some of the code was written for another purpose and copied into
+Xmlrpc-c.  Its copyright owners license the code under a different
+license:
+
+The Expat Licence applies to the contents of the directory lib/expat,
+the ABYSS Web Server License applies to the contents of the directory
+lib/abyss and parts of the file src/xmlrpc_abyss.c.
+
+The Python 1.5.2 license applies to parts of the file
+src/xmlrpc_base64.c.
+
+And as for the tools/ directory, you'll have to examine the licenses
+on your own.
+
+These same licenses have been offered throughout Xmlrpc-c's history.
+
+
+                     XML-RPC For C/C++ License
+                     -------------------------
+
+Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+Copyright (C) 2001 by Eric Kidd. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission. 
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+
+                     Expat License
+                     -------------
+
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+                     ABYSS Web Server License
+                     ------------------------
+
+Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission. 
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+
+
+                     Python 1.5.2 License
+                     --------------------
+
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI or Corporation for National Research Initiatives or
+CNRI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+While CWI is the initial source for this software, a modified version
+is made available by the Corporation for National Research Initiatives
+(CNRI) at the Internet address ftp://ftp.python.org.
+
+STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
+CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/doc/CREDITS b/doc/CREDITS
new file mode 100644 (file)
index 0000000..050113a
--- /dev/null
@@ -0,0 +1,19 @@
+Funding for the project that created the original Xmlrpc-c was
+provided in part by the good folks at First Peer, Inc., producers of
+P2P applications.
+
+Eric Kidd developed the original Xmlrpc-c in 2000 and maintained it up
+through June 2001.
+
+Bryan Henderson took over as maintainer in October 2004.
+
+Xmlrpc-c contains (and relies on for some server functions) a derivation
+of the Abyss web server by Moez Mahfoudh.
+
+Xmlrpc-c contains (and relies on) a derivation of the Expat XML
+parser, written by James Clark.
+
+The base64 code was derived from what Jack Jansen developed for Python.
+
+For more history, including credits for more minor contributions, see
+the HISTORY file.
diff --git a/doc/DEVELOPING b/doc/DEVELOPING
new file mode 100644 (file)
index 0000000..d5c53b0
--- /dev/null
@@ -0,0 +1,82 @@
+Here are some notes to help you develop code for Xmlrpc-c.  I include
+as "developing" debugging to figure out why Xmlrpc-c doesn't work for
+you.
+
+CODE LIBRARY
+------------
+
+The master Xmlrpc-c source code tree is the CVS repository on
+Sourceforge.  Anybody can read it; only the maintainer can commit to
+it.  If you're not the maintainer, simply use a 'cvs diff' command in
+your CVS working directory to create a patch file that embodies your
+changes and email that to the maintainer.  He can easily apply that
+patch to his own CVS working directory and then commit the changes.
+
+
+MAKE VARIABLES
+--------------
+
+You can pass make variable values to GNU Make to change the build.
+There are two common ways to do this:
+
+  1) Like this:
+
+     $ make MYVAR=myvalue
+
+  2) Via an environment variable, like this:
+
+     $ MYVAR=myvalue make
+
+     or
+     $ export MYVAR=myvalue
+     $ make
+
+See GNU Make and shell documentation for details.
+
+In Xmlrpc-c make files, there are two make variables that add
+arbitrary options to every compile command: CADD and CFLAGS_PERSONAL.
+
+They both do the same thing.  CADD is meant to be set on an individual
+make command, whereas CFLAGS_PERSONAL is meant to be a long-lived
+environment variable.  CFLAGS_PERSONAL is for flags you like on all
+your compiles, but maybe others don't.
+
+One of my favorite CADD settings is CADD=--save-temps.  To the GNU
+Compiler, --save-temps means to create, in addition to the object
+code, a file containing the intermediate preprocessed C code and a
+file containing the intermediate assembler source code.  I can use
+that to debug certain things.
+
+The Xmlrpc-c build uses -g by default with Gcc, so you don't need to
+use CADD to get debugging symbols in your object code.
+
+
+There's also LADD for linker options.
+
+
+CODE STYLE
+----------
+
+The maintainer is pretty particular about coding style, but doesn't
+require anyone to submit code in any particular style.  He changes
+what he thinks isn't maintainable enough as submitted.  You could do
+him a big favor, though, and reduce the chance of him introducing bugs
+into your code, but trying to copy the style you see in existing code.
+The major theme is high level programming -- closer to English prose
+and further from machine instructions.
+
+Probably the most important thing is not to use tabs.  Tabs are
+actually quite common in Unix C programming, but apart from tradition,
+they are a bad idea.  They don't look the same to everyone.  A person
+must suffer an additional configuration step -- setting up tab stops
+in order to see the code the right way.  Spaces, on the other hand,
+look the same to everyone.  Very old editors made it easier to compose
+with tabs than with spaces, but with modern ones, there is no
+difference.
+
+The maintainer tries to catch all tabs in code submitted to him and
+convert them to spaces, but this often leaves the code incorrectly
+indented.  Better to give him code that already has the right number
+of spaces explicitly.
+
diff --git a/doc/HISTORY b/doc/HISTORY
new file mode 100644 (file)
index 0000000..ada3e0f
--- /dev/null
@@ -0,0 +1,61 @@
+For a release-by-release change history, see
+<http://xmlrpc-c.sourceforge.net/change.html>.
+
+XML-RPC For C/C++ was created by Eric Kidd in 2000, when XML-RPC was
+new and vital.  Its development was funded in significant part by
+First Peer, Inc.  Eric released the package in January 2001 and set up
+an extensive project to maintain it.  The project used virtually every
+feature on Sourceforge, had about 8 official developers, and
+distributed code in various formats.  There were mailing lists,
+trackers, CVS branches, RPMs, and a full PHP-based web site, just to
+name a few features of the project.
+
+Then everything ground to a halt in June 2001, with the disappearance
+of Eric.  We don't know what happened to him, but Google searches in
+late 2004 indicated he dropped off the face of the web at that time.
+While people continued to use Xmlrpc-c, and some developed fixes and
+enhancements and posted them to the Sourceforge trackers, the release
+remained frozen at 0.9.10.  The web site also became frozen in time.
+
+In the years that followed the great freeze, XML-RPC became
+marginalized by more sophisticated alternatives such as SOAP.  XML-RPC
+consequently became rather stable and interest in Xmlrpc-c levelled
+off.
+
+This dark age of Xmlrpc-c lasted until November 2004, when Bryan Henderson
+set out to find an RPC mechanism to use in one of his projects.  Bryan
+found XML-RPC and then Xmlrpc-c.  He decided that the two were almost right
+for his needs, but he needed some small extensions.
+
+On finding out that the project was orphaned, Bryan decided to take it
+over.  Bryan became the Sourceforge project administrator through
+Sourceforge's abandonned project process, then gathered the patches
+that had been submitted over the years and made a come-back release
+called 1.0.
+
+Bryan then proceeded to add a lot of features in subsequent releases
+about every two months.  Most of it was code Bryan wrote himself, but
+significant parts were contributed by others, as you can see in the
+detailed history below.  Among the larger enhancements was a new
+C++ interface; the old one was a fairly weak wrapper around the
+C interface and required the user to manage memory and access the
+underlying C structures; the new one used pure C++ principles with
+automatic memory management.
+
+Bryan also wrote a complete user's manual.  Surprisingly, in spite of
+the wide array of features the project had, documentation wasn't one
+of them.  There was only a smattering of information available on how
+to use the package.
+
+One significant change Bryan made to the project was to strip it down
+considerably.  In order to concentrate the small amount of time Bryan
+had available for Xmlrpc-c development on actual code and
+documentation, Bryan had to greatly reduce the amount of bureaucracy
+involved in administering the project and making releases, and reduce
+the set of skills required to do it.  Bryan made static make files
+(for GNU Make) to replace the two extra build stages that originally
+generated make files.  Bryan moved away from Libtool and toward simple
+compiling and linking.  Bryan eliminated all pre-built distributions;
+each of his releases consisted of a single source code tarball, and
+that tarball was not signed.  Bryan removed some redundant sources of
+information from the package and the web site.
diff --git a/doc/INSTALL b/doc/INSTALL
new file mode 100644 (file)
index 0000000..7b15e94
--- /dev/null
@@ -0,0 +1,129 @@
+These are instructions for building Xmlrpc-c from source and installing
+it on a system.
+
+See the README file for information on prerequisites (things you need to 
+have installed before you can build).
+
+
+Essentially, it's just the conventional
+
+  $ ./configure
+  $ make
+  $ make install
+
+You can also do
+
+  $ make check
+
+to run a battery of tests before you install.  But note that it's as common
+for the tests to fail because the tests are broken as because the product
+is broken, so consider the results carefully.
+
+To see it work, run a simple server like this:
+
+  $ examples/xmlrpc_sample_add_server 8080
+
+Then run a client that does an RPC to this server:
+
+  $ examples/xmlrpc_sample_add_client
+
+(I don't mean to imply that the above are consecutive shell commands;
+They can't be, because the server program runs indefinitely).
+
+Also try other sample servers and clients, described in examples/README.
+
+
+You may want to pass a '--prefix' argument to 'configure'.  See
+'./configure --help' for details.
+
+You may also want to disable client XML transports that you won't be
+using.  In particular, the Libwww transport can be inconvenient, because
+it typically uses about 20 shared libraries.  Any XML-RPC client
+program that uses Xmlrpc-c, whether or not the program uses any of the
+libwww facilities, must attach all those libraries, and that can take
+a significant amount of time.
+
+See './configure --help' for the options that disable certain transports.
+
+
+COMMON PROBLEMS
+---------------
+
+Improper -config files
+----------------------
+
+The most common problem building Xmlrpc-c is one of improperly installed
+prerequisite libraries, namely Libwww and Curl.  These libraries are
+designed to be installed along with a -config program (libwww-config
+and curl-config) that tells builders of dependent packages (such as
+Xmlrpc-c) how to use them.  When the -config program is wrong, you get
+Xmlrpc-c build failures with messages about undefined references.
+
+The exact nature of the problems with -config programs can be quite
+involved, especially since there is no guarantee that a -config
+program can do what's required of it in every situation.  But I'll
+explain the basic problem.  For simplicity, I'll talk specifically
+about Curl, but the principles apply to any library that has a -config
+program.
+
+The point of curl-config is to describe how Curl is installed on your
+particular system.  You have choices of where to install the various parts
+and what prerequisites to build into them, and curl-config is how you
+communicate those choices to the Xmlrpc-c make files.
+
+Curl's builder automatically creates a curl-config program for you,
+but you should not think of it as part of Curl.  It's really a
+configuration file -- something that tells how your particular system
+is put together.  The Curl builder is not smart enough to know exactly
+what to put in curl-config; it just builds one that works for most
+people.  The local system administrator is actually responsible for
+the contents of curl-config.
+
+One rather complex way in which the curl-config that the Curl builder
+builds can be wrong is that it often indicates that to link to the
+Curl library, you need a "-L /usr/lib" option (or something like that
+-- an option that adds to the linker's search path a directory that is
+already in it).  This is usually unnecessary because the directory is
+already in the search path, and often breaks things because it puts
+the directory too early in the search path.  If your curl-config says to
+link with -L /usr/lib, you should normally edit it to remove that.
+
+As an example of how -L /usr/lib breaks things, here is a problem that
+is often reported: The user has Xmlrpc-c installed on his system, but
+wants to build a new one to replace it, or to use for a particular
+project instead of the system version.  But the build of the new
+version fails with undefined references to symbol "xmlrpc_foo".
+xmlrpc_foo is a new symbol - it was added to Xmlrpc-c in a recent
+release.  The version of Xmlrpc-c installed on the system is too old
+to have it.  The make file obviously specifies the path to the current
+libraries that the user just built in the link library search order,
+but the link is picking up the old system version instead.  Why?
+Because the link options say to search /usr/lib _before_ the local
+build directory.  And it does that because curl-config erroneously
+says that you need a -L /usr/lib link option to find the Curl library.
+
+64 Bit Linux -fPIC 
+------------------
+
+The GNU link-editor produces this error message when building the C++
+libraries for certain 64 bit machines:
+
+  relocation R_X86_64_32 against `a local symbol' can not be used when
+  making a shared object; recompile with -fPIC
+
+Xmlrpc-c 1.06 C++ libraries are not designed for these platforms.
+(Releases starting with 1.07 are).
+
+You can work around this by adding a setting of the CADD make variable
+to your make command:
+
+  make CADD=-fPIC
+
+
+WINDOWS
+-------
+
+All of the above is essentially for Unix-type operating systems.  To
+build and use Xmlrpc-c on Windows, see the file
+Windows/ReadMeWin32.txt.
+
diff --git a/doc/SECURITY b/doc/SECURITY
new file mode 100644 (file)
index 0000000..c3566c2
--- /dev/null
@@ -0,0 +1,50 @@
+Security Advisories
+===================
+
+The Xmlrpc-c maintainer will normally post security advisories related
+to xmlrpc-c to the xmlrpc-c-announce mailing list.  You can subscribe
+to this using the web:
+
+  http://xmlrpc-c.sourceforge.net/lists.php
+
+You will also find a list of all known bugs including those with
+security ramifications, in the release notes on Sourceforge.  To see
+the release notes for a release, go to the file download page and
+click on the release name.  The list is current only for the most
+current release -- i.e. we stop adding to the list for release N after
+we release N+1.
+
+
+XML-RPC Security
+================
+
+There are some security issues inherent in XML-RPC:
+
+  1) XML-RPC messages are not encrypted at the XML-RPC level.  This
+     means that unless you encrypt them at some lower level, someone
+     with sufficient access to the network can see them with standard
+     packet-sniffing and network administration tools.
+
+     This is especially dangerous because XML-RPC is a stateless protocol.
+     If you include reusable authentication tokens in an XML-RPC call, they
+     can probably be sniffed and used by attackers.
+
+     You can solve this problem by using SSL under HTTP.  This is possible
+     with Xmlrpc-c, but it's nontrivial to set up and the Xmlrpc-c
+     documentation doesn't tell you how.
+
+  2) There are no permission restrictions and no authentication built
+     into Xmlrpc-c by default -- any client can call any method on any
+     visible server and neither can know for sure to whom it is talking.
+
+     If you need permission and authentication, you either have to put
+     it above the XML-RPC layer or below.  For a server, above means in
+     the method code you supply and register with the Xmlrpc-c server
+     facilities; below means something like a firewall that lets clients
+     only from a certain IP address connect to your server.
+
+  3) XML-RPC is a complex protocol based on complex data structures.
+     Layers and layers of potentially buggy code gets run between the
+     time network data is received, and the time it is understood; and
+     conversely between the time data is conceived and the time it
+     gets sent.
diff --git a/doc/TESTING b/doc/TESTING
new file mode 100644 (file)
index 0000000..50d785d
--- /dev/null
@@ -0,0 +1,96 @@
+In general, we want to run as many automated test tools on the
+Xmlrpc-c libraries as possible.  Before releasing a new release,
+please run as many of these tests as possible.
+
+
+Included Test Suites
+--------------------
+
+The 'test' program tests core functions.  These are functions that
+don't involve HTTP communications.  So obviously, it doesn't do any
+end-to-end client/server tests.
+
+The program is in src/test/test.  You have to build that explicitly (with
+src/test/ as your current directory, do a 'make'); a top level 'make all'
+doesn't build it.  (Reason: it's a tricky build, and we don't a user's
+build to fail just because of this program that a user doesn't need).
+
+src/cpp/cpptest is similar for the C++ libraries.
+
+Note: Before Release 1.03, 'test' was called 'rpctest' and both it
+and 'cpptest' were in the src/ directory and were built by 'make all'.
+
+
+Memory Leaks
+------------
+
+(Linux only?) Install Owen Taylor's 'memprof' utility. This program
+includes a malloc debugger and a conservative garbage collector. To run it,
+type:
+
+  memprof test
+
+This should report any memory leaks which occur while the test suites are
+running.
+
+
+Electric Fence
+--------------
+
+(Most Unix platforms.) Install Bruce Perens' Electric Fence library, and
+read the man pages carefully. Link 'test' against '-lefence', and run it
+with the following sets of environment variables:
+
+  1) (Default environment.)
+     Test for heap block overruns.
+
+  2) EF_PROTECT_BELOW=1
+     Test for heap block underruns.
+
+  3) EF_PROTECT_FREE=1
+     Test for doubly-freed memory and illegal accesses to freed memory.
+
+  4) EF_ALIGNMENT=0
+     Test for very small block overruns. This is an important test, but
+     it may not work on some platforms. Please see the efence manpage for
+     more information.
+
+(After each run, unset the environment variables from the previous run.)
+
+Using a Bourne shell (such as bash) you can run all these tests as follows:
+
+  test
+  EF_PROTECT_BELOW=1 test
+  EF_PROTECT_FREE=1 test
+  EF_ALIGNMENT=0 test
+
+Alternatively, if you have a copy of Purify installed, please run that.
+
+
+End-to-End Tests
+----------------
+
+To test Abyss and the client XML transports, use the example
+programs examples/sample_add_server and examples/sample_add_client:
+
+  $ export XMLRPC_TRACE_XML=1
+  $ examples/sample_add_server 8080&
+  $ examples/sample_add_client
+
+Note that we use XMLRPC_TRACE_XML so we can see the XML flying by on
+both sides of the connection.
+
+Note that the Port 8080 is hardcoded in sample_add_client.
+
+Note that sample_add_client uses only the default XML transport.
+
+
+You can do more extensive client testing with the 'xmlrpc' program
+(tools/xmlrpc/xmlrpc).
+
+
+Tips
+----
+
+To debug Abyss without threads, don't pass -D_UNIX or -D_WIN32. The server
+will run in a single-threaded mode.
diff --git a/doc/TODO b/doc/TODO
new file mode 100644 (file)
index 0000000..514b4a4
--- /dev/null
+++ b/doc/TODO
@@ -0,0 +1,71 @@
+Here are some changes we'd like to see to Xmlrpc-c.  While it's unlikely
+anyone will ever do them, the list is at least useful as an indication of
+what direction the maintainer wants the package to take, and that should
+be useful to anyone proposing changes of any kind.
+
+
+FUNCTIONAL CHANGES
+------------------
+
+Make xmlrpc_server_abyss() catch a SIGTERM and terminate cleanly.
+
+Make a system.shutdown XML-RPC method to send SIGTERM to its server.
+Don't know what kind of security.
+
+Provide an interface for Abyss servers where the user accepts the TCP
+connection and passes to Xmlrpc-c the open socket.  This would be
+useful for inetd servers, among others.  For the C++ interface, this
+should be a new constructor option to create a server with no socket
+and a doRpc() method that has a connected socket as parameter.
+
+Put details in the manual for the xmlrpc-c/server_abyss.hpp interface:
+libxmlrpc_server_abyss++.html.
+
+Implement pluggable XML transports on the server side like on the
+client side.
+
+Create a non-XML non-HTTP efficient transport, client and server.
+The tools/binmode-rpc-kit/ directory might be useful.  Consider XDR.
+
+Make clients and servers reentrant (this requires getting or making
+reentrant HTTP libraries).
+
+Change the argument order of asynchronous response callbacks to be
+more consistent with the xmlrpc_client_call_asynch function.  Also
+take a look at the server method callback.
+
+Make an optional destructor function for XMLRPC_TYPE_C_PTR.
+
+Return XMLRPC_LIMIT_EXCEEDED_ERROR when nesting limits are exceeded.
+This will break binary and source API compatibility in a very minor
+way.
+
+Make a Perl interface to Xmlrpc-c libraries.  This would be better than the
+existing Perl RPC::XML modules because the latter are Perl all the way down
+to the sockets and are thus very slow.
+
+Don't use xmlrpc_value for things that aren't part of an XML-RPC call or
+response.  It's confusing.  In particular, we use an xmlrpc_value
+array to pass the parameters of an RPC to xmlrpc_client_call(), and it
+should instead be a normal C array plus count, or variable argument list.
+
+Don't use XML-RPC fault codes internally.  It's confusing.  Plus, there's
+no need for fault codes at all.  Just use the string descriptions.
+
+
+IMPLEMENTATION CHANGES
+----------------------
+
+Replace dynamically created make files with static ones based on GNU make.
+
+Use function pointers to access cleanup code in xmlrpc_DECREF?
+
+Or even better: Should we create some kind of class-like system to declare
+XML-RPC types, with a per-type dispatch table?
+
+Fix abstract XML parser API to access children via functions named
+xml_element_child(env,elem,index) and xml_element_child_count(env,elem).
+Clean up corresponding client code.
+
+Make the C++ server implementation less based on the C functions.
+
diff --git a/doc/configure_doc b/doc/configure_doc
new file mode 100644 (file)
index 0000000..953a904
--- /dev/null
@@ -0,0 +1,189 @@
+Xmlrpc-c's 'configure' program is a GNU Autoconf configurator -- i.e.
+it is created by GNU Autoconf.  This is the standard configurator you
+find throughout the open source software world.  Here are the instructions
+for 'configure' from GNU Autoconf; in most packages, you find these in
+a file called INSTALL.
+
+
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/examples/.cvsignore b/examples/.cvsignore
new file mode 100644 (file)
index 0000000..5835a25
--- /dev/null
@@ -0,0 +1,13 @@
+gen_sample_add_xml
+meerkat-app-list
+query-meerkat
+synch_client
+xmlrpc_asynch_client
+auth_client
+xmlrpc_inetd_server
+xmlrpc_loop_server
+xmlrpc_sample_add_client
+xmlrpc_sample_add_server
+xmlrpc_server_validatee
+xmlrpc_socket_server
+*.cgi
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644 (file)
index 0000000..7eb8e96
--- /dev/null
@@ -0,0 +1,141 @@
+# Since the programs in this directories are examples for the user, this
+# make file should be as ordinary as possible.  It should not rely heavily
+# on included make files or configuration parameters.  It should not use
+# libtool.  Also, we don't try to build or rebuild the libraries on which
+# these programs depend.
+
+
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/..
+BUILDDIR = $(SRCDIR)
+endif
+
+default: all
+
+include $(BUILDDIR)/Makefile.config
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+LDFLAGS = $(LADD)
+
+# If this were a real application, working from an installed copy of
+# Xmlrpc-c, XMLRPC_C_CONFIG would just be 'xmlrpc-c-config'.  It would be
+# found in the user's PATH.
+XMLRPC_C_CONFIG = $(BUILDDIR)/xmlrpc-c-config.test
+
+CLIENTPROGS = \
+  auth_client \
+  query-meerkat \
+  synch_client \
+  xmlrpc_sample_add_client \
+  xmlrpc_asynch_client \
+
+SERVERPROGS_CGI = \
+  xmlrpc_sample_add_server.cgi
+
+SERVERPROGS_ABYSS = \
+  xmlrpc_inetd_server \
+  xmlrpc_socket_server \
+  xmlrpc_loop_server \
+  xmlrpc_sample_add_server \
+  xmlrpc_server_validatee \
+
+# Build up PROGS:
+PROGS = 
+
+ifeq ($(ENABLE_ABYSS_SERVER),yes)
+  PROGS += $(SERVERPROGS_ABYSS)
+endif
+
+PROGS += gen_sample_add_xml
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  PROGS += $(CLIENTPROGS)
+endif
+
+ifeq ($(ENABLE_CGI_SERVER),yes)
+  PROGS += $(SERVERPROGS_CGI) 
+endif
+
+INCLUDES = $(shell $(XMLRPC_C_CONFIG) client abyss-server --cflags)
+
+LDADD_CLIENT = \
+  $(shell $(XMLRPC_C_CONFIG) client --ldadd)
+
+LDADD_SERVER_ABYSS = \
+  $(shell $(XMLRPC_C_CONFIG) abyss-server --ldadd)
+
+LDADD_SERVER_CGI = \
+  $(shell $(XMLRPC_C_CONFIG) cgi-server --ldadd)
+
+LDADD_BASE = \
+  $(shell $(XMLRPC_C_CONFIG) --ldadd)
+
+all: $(PROGS)
+
+ifeq ($(ENABLE_CPLUSPLUS),yes)
+  all: cpp/all
+endif
+
+.PHONY: cpp/all
+cpp/all:
+       $(MAKE) -C $(dir $@) $(notdir $@)
+
+$(CLIENTPROGS):%:%.o
+       $(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_CLIENT)
+
+$(SERVERPROGS_CGI):%.cgi:%_cgi.o
+       $(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_CGI)
+
+$(SERVERPROGS_ABYSS):%:%.o
+       $(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_ABYSS)
+
+gen_sample_add_xml:%:%.o
+       $(CCLD) -o $@ $(LDFLAGS) $^ $(LDADD_BASE)
+
+%.o:%.c
+       $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+*.c: config.h xmlrpc_amconfig.h
+
+config.h:
+       $(LN_S) $(BUILDDIR)/xmlrpc_config.h $@
+xmlrpc_amconfig.h:
+       $(LN_S) $(BUILDDIR)/$@ .
+
+include $(SRCDIR)/Makefile.common
+
+.PHONY: clean
+clean: clean-common
+       rm -f $(PROGS) config.h xmlrpc_amconfig.h
+       $(MAKE) -C cpp clean
+
+.PHONY: distclean
+distclean: clean
+
+BINDIR=$(DESTDIR)$(bindir)
+
+FILENAME_GENERATOR = "echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'"
+
+INSTCMD =  "$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p \
+  $(BINDIR)/`$(FILENAME_GENERATOR)`"
+
+.PHONY: install
+install: $(PROGS)
+       @$(NORMAL_INSTALL)
+       $(MKINSTALLDIRS) $(BINDIR)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo "$(INSTCMD)"; $(INSTCMD); \
+         else :; \
+          fi; \
+       done
+
+.PHONY: check
+check:
+
+.PHONY: dep depend
+dep depend:
+# We don't do dependencies in this directory, because it's supposed to be
+# an example of what a program outside this package would do, so we can't
+# go weaving it into the rest of the package.  Ergo, a developer must
+# carefully clean and remake examples as he updates other parts of the tree.
diff --git a/examples/README b/examples/README
new file mode 100644 (file)
index 0000000..46b02b4
--- /dev/null
@@ -0,0 +1,34 @@
+This directory contains working examples of uses of XML-RPC-c.  There
+are XML-RPC servers and XML-RPC clients that use the Xmlrpc-c libraries.
+
+The simplest example is the 'query-meerkat' program, which contacts an
+XML-RPC server that O'Reilly operates on the Internet called Meerkat.
+Meerkat provides an RPC that returns a list of new articles that match
+a specified search pattern.  Run 'query-meerkat' like this example:
+
+  $ ./query-meerkat Linux
+
+This responds with a list of new articles that contain the work "Linux",
+according to O'reilly's Meerkat service.
+
+
+The simplest server program is 'xmlrpc_sample_add_server'.  This
+implements a single XML-RPC method called 'sample.add'.  All it does is
+add two numbers and return the sum.  You can run such a server like
+this:
+
+  $ ./xmlrpc_sample_add_server 8080
+
+The server this runs is based on the Abyss HTTP server.  file.  The
+argument tell it to listen on TCP Port 8080 for RPCs.  It puts log
+information in /tmp, so be sure to look there.
+
+A client program that goes along with this server is
+'xmlrpc_sample_add_client'.  All this client does is make an XML-RPC
+request to Port 8080 of 'localhost' to add the numbers 5 and 7 and
+print the result on Standard Output.
+
+You can run such a client like this:
+
+  $ ./xmlrpc_sample_add_client
+
diff --git a/examples/auth_client.c b/examples/auth_client.c
new file mode 100644 (file)
index 0000000..dd6a2b4
--- /dev/null
@@ -0,0 +1,80 @@
+/* A demonstration of using HTTP basic authentication with XML-RPC.
+**
+** In general, you shouldn't write XML-RPC servers which require basic
+** authenticaion. (Few XML-RPC clients are capable of it, and it's not part of
+** any standard.) Instead, you should pass any authentication information
+** as a regular XML-RPC parameter (or look into using SSL).
+**
+** But certain XML-RPC servers, including Zope, rely heavily on HTTP
+** basic authentication. Here's how to talk to them. */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+
+#include "config.h"  /* information about this build environment */
+
+#define NAME       "XML-RPC C Auth Client"
+#define VERSION    "1.0"
+#define SERVER_URL "http://localhost:8080/RPC2"
+
+static void die_if_fault_occurred (xmlrpc_env *env)
+{
+    if (env->fault_occurred) {
+        fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
+                env->fault_string, env->fault_code);
+        exit(1);
+    }
+}
+
+int 
+main(int           const argc, 
+     const char ** const argv ATTR_UNUSED) {
+
+    xmlrpc_env env;
+    xmlrpc_server_info * server;
+    xmlrpc_value * result;    
+    xmlrpc_int sum;
+    
+    if (argc-1 > 0) {
+        fprintf(stderr, "There are no arguments.  You specified %d", argc-1);
+        exit(1);
+    }
+
+    /* Start up our XML-RPC client library. */
+    xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION);
+    xmlrpc_env_init(&env);
+
+    /* Make a new object to represent our XML-RPC server. */
+    server = xmlrpc_server_info_new(&env, SERVER_URL);
+    die_if_fault_occurred(&env);
+
+    /* Set up our authentication information. */
+    xmlrpc_server_info_set_basic_auth(&env, server, "jrandom", "secret");
+    die_if_fault_occurred(&env);
+
+    result = 
+        xmlrpc_client_call_server(
+            &env, server, "sample.add", "(ii)", 
+            (xmlrpc_int32) 5, (xmlrpc_int32) 7);
+    die_if_fault_occurred(&env);
+
+    /* Dispose of our server object. */
+    xmlrpc_server_info_free(server);
+    
+    /* Get the authentication information and print it out. */
+    xmlrpc_read_int(&env, result, &sum);
+    die_if_fault_occurred(&env);
+    printf("The sum is %d\n", sum);
+    
+    /* Dispose of our result value. */
+    xmlrpc_DECREF(result);
+
+    /* Shut down our XML-RPC client library. */
+    xmlrpc_env_clean(&env);
+    xmlrpc_client_cleanup();
+
+    return 0;
+}
diff --git a/examples/cpp/.cvsignore b/examples/cpp/.cvsignore
new file mode 100644 (file)
index 0000000..99bb114
--- /dev/null
@@ -0,0 +1,6 @@
+meerkat-app-list
+xmlrpc_inetd_server
+xmlrpc_loop_server
+xmlrpc_sample_add_server
+xmlrpc_sample_add_client
+sample_add_client_complex
diff --git a/examples/cpp/Makefile b/examples/cpp/Makefile
new file mode 100644 (file)
index 0000000..8d59247
--- /dev/null
@@ -0,0 +1,98 @@
+# Since the programs in this directories are examples for the user, this
+# make file should be as ordinary as possible.  It should not rely heavily
+# on included make files or configuration parameters.  It should not use
+# libtool.  Also, we don't try to build or rebuild the libraries on which
+# these programs depend.
+
+
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+BUILDDIR = ../..
+endif
+
+default: all
+
+include $(BUILDDIR)/Makefile.config
+
+CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+LDFLAGS = $(LADD)
+
+# If this were a real application, working from an installed copy of
+# Xmlrpc-c, XMLRPC_C_CONFIG would just be 'xmlrpc-c-config'.  It would be
+# found in the user's PATH.
+XMLRPC_C_CONFIG = $(BUILDDIR)/xmlrpc-c-config.test
+
+
+SERVERPROGS_ABYSS = \
+  xmlrpc_inetd_server \
+  xmlrpc_loop_server \
+  xmlrpc_sample_add_server \
+
+LEGACY_CLIENTPROGS = \
+  meerkat-app-list
+
+CLIENTPROGS = \
+  xmlrpc_sample_add_client \
+  sample_add_client_complex \
+
+# Build up PROGS:
+PROGS = 
+
+ifeq ($(ENABLE_ABYSS_SERVER),yes)
+  PROGS += $(SERVERPROGS_ABYSS)
+endif
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  PROGS += $(CLIENTPROGS) $(LEGACY_CLIENTPROGS)
+endif
+
+INCLUDES = $(shell $(XMLRPC_C_CONFIG) c++2 client abyss-server --cflags)
+
+LDADD_SERVER_ABYSS = \
+  $(shell $(XMLRPC_C_CONFIG) c++2 abyss-server --ldadd)
+
+LDADD_CLIENT = \
+  $(shell $(XMLRPC_C_CONFIG) c++2 client --ldadd)
+
+LDADD_BASE = \
+  $(shell $(XMLRPC_C_CONFIG) c++2 --ldadd)
+
+LDADD_LEGACY_CLIENT = \
+  $(shell $(XMLRPC_C_CONFIG) c++ client --ldadd)
+
+all: $(PROGS)
+
+$(SERVERPROGS_ABYSS):%:%.o
+       $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_ABYSS)
+
+$(LEGACY_CLIENTPROGS):%:%.o
+       $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_LEGACY_CLIENT)
+
+$(CLIENTPROGS):%:%.o
+       $(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_CLIENT)
+
+%.o:%.cpp
+       $(CXX) -c $(INCLUDES) $(CXXFLAGS) $<
+
+*.c: config.h xmlrpc_amconfig.h
+
+config.h:
+       $(LN_S) $(BUILDDIR)/xmlrpc_config.h $@
+xmlrpc_amconfig.h:
+       $(LN_S) $(BUILDDIR)/$@ .
+
+include $(SRCDIR)/Makefile.common
+
+.PHONY: clean
+clean: clean-common
+       rm -f $(PROGS) config.h xmlrpc_amconfig.h
+
+.PHONY: distclean
+distclean: clean
+
+.PHONY: dep depend
+dep depend:
+# We don't do dependencies in this directory, because it's supposed to be
+# an example of what a program outside this package would do, so we can't
+# go weaving it into the rest of the package.  Ergo, a developer must
+# carefully clean and remake examples as he updates other parts of the tree.
diff --git a/examples/cpp/meerkat-app-list.cpp b/examples/cpp/meerkat-app-list.cpp
new file mode 100644 (file)
index 0000000..69f0f8d
--- /dev/null
@@ -0,0 +1,106 @@
+// List recently-released Linux applications. (Written in C++.)
+// For more details about O'Reilly's excellent Meerkat news service, see:
+// http://www.oreillynet.com/pub/a/rss/2000/11/14/meerkat_xmlrpc.html */
+
+#include <iostream>
+#include <sstream>
+#include <string>
+
+using namespace std;
+
+#include <xmlrpc-c/oldcppwrapper.hpp>
+
+#define NAME           "XML-RPC C++ Meerkat Query Demo"
+#define VERSION        "0.1"
+#define MEERKAT_URL    "http://www.oreillynet.com/meerkat/xml-rpc/server.php"
+#define SOFTWARE_LINUX (6)
+
+static void
+list_apps(unsigned int const hours) {
+
+    // Build our time_period parameter.
+    ostringstream time_period_stream;
+    time_period_stream << hours << "HOUR";
+    string const time_period(time_period_stream.str());
+
+    // Assemble our meerkat query recipe.
+    XmlRpcValue recipe = XmlRpcValue::makeStruct();
+    recipe.structSetValue("category", XmlRpcValue::makeInt(SOFTWARE_LINUX));
+    recipe.structSetValue("time_period", XmlRpcValue::makeString(time_period));
+    recipe.structSetValue("descriptions", XmlRpcValue::makeInt(76));
+
+    // Build our parameter array.
+    XmlRpcValue param_array(XmlRpcValue::makeArray());
+    param_array.arrayAppendItem(recipe);
+
+    // Create a client pointing to Meerkat.
+    XmlRpcClient meerkat(MEERKAT_URL);
+
+    // Perform the query.
+    XmlRpcValue const apps(meerkat.call("meerkat.getItems", param_array));
+
+    // Print our results.
+    size_t const app_count(apps.arraySize());
+    bool first;
+    size_t i;
+    for (i = 0, first=false; i < app_count; ++i, first = false) {
+        XmlRpcValue const app(apps.arrayGetItem(i));
+
+        // Get some information about our application.
+        string const title(app.structGetValue("title").getString());
+        string const link(app.structGetValue("link").getString());
+        string const description(
+            app.structGetValue("description").getString());
+    
+        // Print a separator line if necessary.
+        if (!first)
+            cout << endl;
+
+        // Print this application entry.
+        if (description.size() > 0)
+            cout << title << endl << description << endl << link << endl;
+        else
+            cout << title << endl << description << endl << link << endl;
+    }
+}
+
+
+
+int
+main(int argc, char **argv) {
+    int retval;
+    unsigned int hours;
+
+    // Parse our command-line arguments.
+    if (argc == 1) {
+        hours = 25;
+    } else if (argc == 2) {
+        hours = atoi(argv[1]);
+    }
+    if (hours == 0) {
+        cerr << "Hours must be positive" << endl;
+        exit(1);
+    }
+    if (hours > 49) {
+        cerr << "It's not nice to ask for > 49 hours at once." << endl;
+        exit(1);    
+    }
+
+    // Start up our client library.
+    XmlRpcClient::Initialize(NAME, VERSION);
+
+    // Call our implementation, and watch out for faults.
+    try {
+        list_apps(hours);
+        retval = 0;
+    } catch (XmlRpcFault& fault) {
+        cerr << argv[0] << ": XML-RPC fault #" << fault.getFaultCode()
+             << ": " << fault.getFaultString() << endl;
+        retval = 1;
+    }
+
+    // Shut down our client library.
+    XmlRpcClient::Terminate();
+
+    return retval;
+}
diff --git a/examples/cpp/sample_add_client_complex.cpp b/examples/cpp/sample_add_client_complex.cpp
new file mode 100644 (file)
index 0000000..41cef39
--- /dev/null
@@ -0,0 +1,71 @@
+/*=============================================================================
+                        sample_add_client_complex.cpp
+===============================================================================
+  This is an example of an XML-RPC client that uses XML-RPC for C/C++
+  (Xmlrpc-c).
+
+  In particular, it uses the complex lower-level interface that gives you
+  lots of flexibility but requires lots of code.  Also see
+  xmlrpc_sample_add_server, which does the same thing as this program,
+  but with much simpler code because it uses a simpler facility of
+  Xmlrpc-c.
+
+  This program actually gains nothing from using the more difficult
+  facility.  It is for demonstration purposes.
+=============================================================================*/
+
+#include <cassert>
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <xmlrpc-c/girerr.hpp>
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/client.hpp>
+
+using namespace std;
+
+int
+main(int argc, char **) {
+
+    if (argc-1 > 0) {
+        cerr << "This program has no arguments" << endl;
+        exit(1);
+    }
+
+    try {
+        xmlrpc_c::clientXmlTransport_curl myTransport(
+            xmlrpc_c::clientXmlTransport_curl::constrOpt()
+            .no_ssl_verifyhost(true)
+            .user_agent("sample_add/1.0"));
+
+        xmlrpc_c::client_xml myClient(&myTransport);
+
+        string const methodName("sample.add");
+
+        xmlrpc_c::paramList sampleAddParms;
+        sampleAddParms.add(xmlrpc_c::value_int(5));
+        sampleAddParms.add(xmlrpc_c::value_int(7));
+
+        xmlrpc_c::rpcPtr myRpcP(methodName, sampleAddParms);
+
+        string const serverUrl("http://localhost:8080/RPC2");
+
+        xmlrpc_c::carriageParm_curl0 myCarriageParm(serverUrl);
+
+        myRpcP->call(&myClient, &myCarriageParm);
+
+        assert(myRpcP->isFinished());
+
+        int const sum(xmlrpc_c::value_int(myRpcP->getResult()));
+            // Assume the method returned an integer; throws error if not
+
+        cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
+
+    } catch (girerr::error const error) {
+        cerr << "Client threw error: " << error.what() << endl;
+    } catch (...) {
+        cerr << "Client threw unexpected error." << endl;
+    }
+
+    return 0;
+}
diff --git a/examples/cpp/xmlrpc_inetd_server.cpp b/examples/cpp/xmlrpc_inetd_server.cpp
new file mode 100644 (file)
index 0000000..fd97424
--- /dev/null
@@ -0,0 +1,65 @@
+/* A simple standalone XML-RPC server based on Abyss that contains a
+   simple one-thread request processing loop.  
+
+   xmlrpc_sample_add_server.cpp is a server that does the same thing, but
+   does it by running a full Abyss daemon in the background, so it has
+   less control over how the requests are served.
+*/
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#include <cassert>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_abyss.hpp>
+
+using namespace std;
+
+class sampleAddMethod : public xmlrpc_c::method {
+public:
+    sampleAddMethod() {
+        // signature and help strings are documentation -- the client
+        // can query this information with a system.methodSignature and
+        // system.methodHelp RPC.
+        this->_signature = "ii";  // method's arguments are two integers
+        this->_help = "This method adds two integers together";
+    }
+    void
+    execute(xmlrpc_c::paramList const& paramList,
+            xmlrpc_c::value *   const  retvalP) {
+        
+        int const addend(paramList.getInt(0));
+        int const adder(paramList.getInt(1));
+        
+        paramList.verifyEnd(2);
+        
+        *retvalP = xmlrpc_c::value_int(addend + adder);
+    }
+};
+
+
+
+int 
+main(int           const, 
+     const char ** const) {
+
+    xmlrpc_c::registry myRegistry;
+
+    xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
+
+    myRegistry.addMethod("sample.add", sampleAddMethodP);
+
+    xmlrpc_c::serverAbyss myAbyssServer(
+        myRegistry,
+        8080,              // TCP port on which to listen
+        "/tmp/xmlrpc_log"  // Log file
+        );
+
+    myAbyssServer.runConn(STDIN_FILENO);
+        /* This reads the HTTP POST request from Standard Input and
+           executes the indicated RPC.
+        */
+    return 0;
+}
diff --git a/examples/cpp/xmlrpc_loop_server.cpp b/examples/cpp/xmlrpc_loop_server.cpp
new file mode 100644 (file)
index 0000000..6cc4293
--- /dev/null
@@ -0,0 +1,68 @@
+/* A simple standalone XML-RPC server based on Abyss that contains a
+   simple one-thread request processing loop.  
+
+   xmlrpc_sample_add_server.cpp is a server that does the same thing, but
+   does it by running a full Abyss daemon in the background, so it has
+   less control over how the requests are served.
+*/
+
+#include <cassert>
+#include <iostream>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_abyss.hpp>
+
+using namespace std;
+
+class sampleAddMethod : public xmlrpc_c::method {
+public:
+    sampleAddMethod() {
+        // signature and help strings are documentation -- the client
+        // can query this information with a system.methodSignature and
+        // system.methodHelp RPC.
+        this->_signature = "i:ii";  // method's arguments are two integers
+        this->_help = "This method adds two integers together";
+    }
+    void
+    execute(xmlrpc_c::paramList const& paramList,
+            xmlrpc_c::value *   const  retvalP) {
+        
+        int const addend(paramList.getInt(0));
+        int const adder(paramList.getInt(1));
+        
+        paramList.verifyEnd(2);
+        
+        *retvalP = xmlrpc_c::value_int(addend + adder);
+    }
+};
+
+
+
+int 
+main(int           const, 
+     const char ** const) {
+
+    xmlrpc_c::registry myRegistry;
+
+    xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
+
+    myRegistry.addMethod("sample.add", sampleAddMethodP);
+
+    xmlrpc_c::serverAbyss myAbyssServer(
+        myRegistry,
+        8080,              // TCP port on which to listen
+        "/tmp/xmlrpc_log"  // Log file
+        );
+
+    while (true) {
+        cout << "Waiting for next RPC..." << endl;
+
+        myAbyssServer.runOnce();
+            /* This waits for the next connection, accepts it, reads the
+               HTTP POST request, executes the indicated RPC, and closes
+               the connection.
+            */
+    }
+    return 0;
+}
diff --git a/examples/cpp/xmlrpc_sample_add_client.cpp b/examples/cpp/xmlrpc_sample_add_client.cpp
new file mode 100644 (file)
index 0000000..00699b1
--- /dev/null
@@ -0,0 +1,39 @@
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <xmlrpc-c/girerr.hpp>
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/client_simple.hpp>
+
+using namespace std;
+
+int
+main(int argc, char **) {
+
+    if (argc-1 > 0) {
+        cerr << "This program has no arguments" << endl;
+        exit(1);
+    }
+
+    try {
+        string const serverUrl("http://localhost:8080/RPC2");
+        string const methodName("sample.add");
+
+        xmlrpc_c::clientSimple myClient;
+        xmlrpc_c::value result;
+        
+        myClient.call(serverUrl, methodName, "ii", &result, 5, 7);
+
+        int const sum = xmlrpc_c::value_int(result);
+            // Assume the method returned an integer; throws error if not
+
+        cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
+
+    } catch (girerr::error const error) {
+        cerr << "Client threw error: " << error.what() << endl;
+    } catch (...) {
+        cerr << "Client threw unexpected error." << endl;
+    }
+
+    return 0;
+}
diff --git a/examples/cpp/xmlrpc_sample_add_server.cpp b/examples/cpp/xmlrpc_sample_add_server.cpp
new file mode 100644 (file)
index 0000000..9658f6d
--- /dev/null
@@ -0,0 +1,60 @@
+#include <cassert>
+#include <stdexcept>
+#include <iostream>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/registry.hpp>
+#include <xmlrpc-c/server_abyss.hpp>
+
+using namespace std;
+
+class sampleAddMethod : public xmlrpc_c::method {
+public:
+    sampleAddMethod() {
+        // signature and help strings are documentation -- the client
+        // can query this information with a system.methodSignature and
+        // system.methodHelp RPC.
+        this->_signature = "i:ii";
+            // method's result and two arguments are integers
+        this->_help = "This method adds two integers together";
+    }
+    void
+    execute(xmlrpc_c::paramList const& paramList,
+            xmlrpc_c::value *   const  retvalP) {
+        
+        int const addend(paramList.getInt(0));
+        int const adder(paramList.getInt(1));
+        
+        paramList.verifyEnd(2);
+        
+        *retvalP = xmlrpc_c::value_int(addend + adder);
+    }
+};
+
+
+
+int 
+main(int           const, 
+     const char ** const) {
+
+    try {
+        xmlrpc_c::registry myRegistry;
+
+        xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
+
+        myRegistry.addMethod("sample.add", sampleAddMethodP);
+        
+        xmlrpc_c::serverAbyss myAbyssServer(
+            myRegistry,
+            8080,              // TCP port on which to listen
+            "/tmp/xmlrpc_log"  // Log file
+            );
+        
+        myAbyssServer.run();
+        // xmlrpc_c::serverAbyss.run() never returns
+        assert(false);
+    } catch (exception const& e) {
+        cerr << "Something failed.  " << e.what() << endl;
+    }
+    return 0;
+}
diff --git a/examples/gen_sample_add_xml.c b/examples/gen_sample_add_xml.c
new file mode 100644 (file)
index 0000000..724f814
--- /dev/null
@@ -0,0 +1,73 @@
+/* This program generates on Standard Output the XML for an XML-RPC
+   call suitable for the xmlrpc_sample_add_server program.
+
+   This is the same XML that the xmlrpc_sample_add_client program sends.
+
+   Use this either as an example of how to use the Xmlrpc-c XML-generating
+   functions or to generate XML that you can use to test an XML-RPC
+   server.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <xmlrpc-c/base.h>
+
+#include "config.h"
+
+static void 
+die_if_fault_occurred (xmlrpc_env *env) {
+    if (env->fault_occurred) {
+        fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
+                env->fault_string, env->fault_code);
+        exit(1);
+    }
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv ATTR_UNUSED) {
+
+    char * const methodName = "sample.add";
+
+    xmlrpc_env env;
+    xmlrpc_value * params;
+    xmlrpc_mem_block * xmlmemblockP;
+
+    if (argc-1 > 0) {
+        fprintf(stderr, "This program has no arguments\n");
+        exit(1);
+    }
+
+    /* Initialize our error-handling environment. */
+    xmlrpc_env_init(&env);
+
+    params = xmlrpc_build_value(&env, "(ii)", 
+                                (xmlrpc_int32) 5, (xmlrpc_int32) 7);
+    
+    die_if_fault_occurred(&env);
+
+    xmlmemblockP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
+
+    xmlrpc_serialize_call(&env, xmlmemblockP, methodName, params);
+
+    die_if_fault_occurred(&env);
+
+    fwrite(XMLRPC_MEMBLOCK_CONTENTS(char, xmlmemblockP), 
+           sizeof(char), 
+           XMLRPC_MEMBLOCK_SIZE(char, xmlmemblockP), 
+           stdout);
+
+    XMLRPC_MEMBLOCK_FREE(char, xmlmemblockP);
+
+    /* Dispose of our parameter array. */
+    xmlrpc_DECREF(params);
+
+    /* Clean up our error-handling environment. */
+    xmlrpc_env_clean(&env);
+    
+    return 0;
+}
+
diff --git a/examples/query-meerkat.c b/examples/query-meerkat.c
new file mode 100644 (file)
index 0000000..e566654
--- /dev/null
@@ -0,0 +1,156 @@
+/* A simple news-searcher, written in C to demonstrate how to use the
+   xmplrpc-c client library.
+
+   This program connects to an XMLRPC server that O'Reilly runs on the
+   Internet, gets some information, and displays it on Standard Output.
+   
+   Note that that server is not in any way designed specifically for xmlrpc-c.
+   It simply implements the XMLRPC protocol, and works with any client that
+   implements XMLRPC.
+   
+   The service that the aforementioned server provides is that it gives you
+   a list of news articles that match a certain regular expression.  You give
+   that regular expression an argument to this client program.
+
+   For more details about O'Reilly's excellent Meerkat news service, see:
+   http://www.oreillynet.com/pub/a/rss/2000/11/14/meerkat_xmlrpc.html
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+
+#include "config.h"  /* information about this build environment */
+
+#define NAME        "XML-RPC C Meerkat Query Demo"
+#define VERSION     "1.0"
+#define MEERKAT_URL "http://www.oreillynet.com/meerkat/xml-rpc/server.php"
+
+struct cmdline {
+    const char * searchArg;
+    int hours;
+};
+
+
+static void
+parseCommandLine(int              const argc, 
+                 const char **    const argv,
+                 struct cmdline * const cmdlineP) {
+
+    if (argc-1 < 1) {
+        fprintf(stderr, "Need at least one argument:  "
+                "A mysql regular expression "
+                "search pattern.  Try 'query-meerkat Linux'\n");
+        exit(1);
+    } else {
+        cmdlineP->searchArg = argv[1];
+
+        if (argc-1 < 2) {
+            cmdlineP->hours = 24;
+        } else {
+            cmdlineP->hours = atoi(argv[2]);
+            if (cmdlineP->hours > 49) {
+                fprintf(stderr, "It's not nice to ask for > 49 hours "
+                        "at once.\n");
+                exit(1);    
+            }
+            if (argc-1 > 2) {
+                fprintf(stderr, "There are at most 2 arguments: "
+                        "search pattern "
+                        "and number of hours.");
+                exit(1);
+            }
+        }
+    }
+}
+
+
+
+static void 
+die_if_fault_occurred(xmlrpc_env * const env) {
+    /* We're a command-line utility, so we abort if an error occurs. */
+    if (env->fault_occurred) {
+        fprintf(stderr, "XML-RPC Fault #%d: %s\n",
+                env->fault_code, env->fault_string);
+        exit(1);
+    }
+}
+
+
+
+/* Hey! We fit in one function. */
+int 
+main(int          const argc, 
+     const char** const argv) {
+
+    struct cmdline cmdline;
+    char time_period[16];
+    xmlrpc_env env;
+    xmlrpc_value *stories, *story;
+    size_t size, i;
+    int first;
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    snprintf(time_period, sizeof(time_period), "%dHOUR", cmdline.hours);
+
+    xmlrpc_env_init(&env);
+
+    /* Set up our client. */
+    xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0);
+
+    die_if_fault_occurred(&env);
+
+    /* Ask Meerkat to look for matching stories. */
+    stories = xmlrpc_client_call(&env, MEERKAT_URL,
+                                 "meerkat.getItems", "({s:s,s:i,s:s})",
+                                 "search", cmdline.searchArg,
+                                 "descriptions", (xmlrpc_int32) 76,
+                                 "time_period", time_period);
+    die_if_fault_occurred(&env);
+    
+    /* Loop over the stories. */
+    size = xmlrpc_array_size(&env, stories);
+    die_if_fault_occurred(&env);
+    first = 1;
+    for (i = 0; i < size; i++) {
+        const char * title;
+        const char * link;
+        const char * description;
+
+        /* Extract the useful information from our story. */
+        story = xmlrpc_array_get_item(&env, stories, i);
+        die_if_fault_occurred(&env);
+        xmlrpc_decompose_value(&env, story, "{s:s,s:s,s:s,*}",
+                               "title", &title,
+                               "link", &link,
+                               "description", &description);
+        die_if_fault_occurred(&env);
+
+        /* Print a separator line if necessary. */
+        if (first)
+            first = 0;
+        else
+            printf("\n");
+
+        /* Print the story. */
+        if (strlen(description) > 0) {
+            printf("%s\n%s\n%s\n", title, description, link);
+        } else {
+            printf("%s\n%s\n", title, link);
+        }
+        free((char*)title);
+        free((char*)link);
+        free((char*)description);
+    }
+    
+    /* Shut down our client. */
+    xmlrpc_DECREF(stories);
+    xmlrpc_env_clean(&env);
+    xmlrpc_client_cleanup();
+
+    return 0;
+}
diff --git a/examples/synch_client.c b/examples/synch_client.c
new file mode 100644 (file)
index 0000000..bf6889a
--- /dev/null
@@ -0,0 +1,66 @@
+/* A simple synchronous XML-RPC client written in C. */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+
+#include "config.h"  /* information about this build environment */
+
+#define NAME "XML-RPC C Test Client synch_client"
+#define VERSION "1.0"
+
+static void die_if_fault_occurred (xmlrpc_env *env)
+{
+    if (env->fault_occurred) {
+        fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
+                env->fault_string, env->fault_code);
+        exit(1);
+    }
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv ATTR_UNUSED) {
+
+    xmlrpc_env env;
+    xmlrpc_value * resultP;
+    const char * state_name;
+
+    if (argc-1 > 0) {
+        fprintf(stderr, "No arguments");
+        exit(0);
+    }
+
+    /* Start up our XML-RPC client library. */
+    xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION);
+
+    /* Initialize our error-handling environment. */
+    xmlrpc_env_init(&env);
+
+    /* Call the famous server at UserLand. */
+    resultP = xmlrpc_client_call(&env, "http://betty.userland.com/RPC2",
+                                 "examples.getStateName",
+                                 "(i)", (xmlrpc_int32) 41);
+    die_if_fault_occurred(&env);
+    
+    /* Get our state name and print it out. */
+    xmlrpc_read_string(&env, resultP, &state_name);
+    die_if_fault_occurred(&env);
+    printf("%s\n", state_name);
+    free((char*)state_name);
+   
+    /* Dispose of our result value. */
+    xmlrpc_DECREF(resultP);
+
+    /* Clean up our error-handling environment. */
+    xmlrpc_env_clean(&env);
+    
+    /* Shutdown our XML-RPC client library. */
+    xmlrpc_client_cleanup();
+
+    return 0;
+}
diff --git a/examples/xmlrpc_asynch_client.c b/examples/xmlrpc_asynch_client.c
new file mode 100644 (file)
index 0000000..ae812e1
--- /dev/null
@@ -0,0 +1,122 @@
+/* A simple asynchronous XML-RPC client written in C, as an example of
+   Xmlrpc-c asynchronous RPC facilities.  This is the same as the 
+   simpler synchronous client xmlprc_sample_add_client.c, except that
+   it adds 3 different pairs of numbers with the summation RPCs going on
+   simultaneously.
+
+   Use this with xmlrpc_sample_add_server.  Note that that server
+   intentionally takes extra time to add 1 to anything, so you can see
+   our 5+1 RPC finish after our 5+0 and 5+2 RPCs.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+
+#include "config.h"  /* information about this build environment */
+
+#define NAME "Xmlrpc-c Asynchronous Test Client"
+#define VERSION "1.0"
+
+static void 
+die_if_fault_occurred (xmlrpc_env * const envP) {
+    if (envP->fault_occurred) {
+        fprintf(stderr, "Something failed. %s (XML-RPC fault code %d)\n",
+                envP->fault_string, envP->fault_code);
+        exit(1);
+    }
+}
+
+
+
+static void 
+handle_sample_add_response(const char *   const server_url,
+                           const char *   const method_name,
+                           xmlrpc_value * const param_array,
+                           void *         const user_data ATTR_UNUSED,
+                           xmlrpc_env *   const faultP,
+                           xmlrpc_value * const resultP) {
+
+    xmlrpc_env env;
+    xmlrpc_int addend, adder;
+    
+    /* Initialize our error environment variable */
+    xmlrpc_env_init(&env);
+
+    /* Our first four arguments provide helpful context.  Let's grab the
+       addends from our parameter array. 
+    */
+    xmlrpc_decompose_value(&env, param_array, "(ii)", &addend, &adder);
+    die_if_fault_occurred(&env);
+
+    printf("RPC with method '%s' at URL '%s' to add %d and %d "
+           "has completed\n", method_name, server_url, addend, adder);
+    
+    if (faultP->fault_occurred)
+        printf("The RPC failed.  %s", faultP->fault_string);
+    else {
+        xmlrpc_int sum;
+
+        xmlrpc_read_int(&env, resultP, &sum);
+        die_if_fault_occurred(&env);
+
+        printf("The sum is  %d\n", sum);
+    }
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv ATTR_UNUSED) {
+
+    char * const serverUrl = "http://localhost:8080/RPC2";
+    char * const methodName = "sample.add";
+
+    xmlrpc_env env;
+    xmlrpc_client * clientP;
+    xmlrpc_int adder;
+
+    if (argc-1 > 0) {
+        fprintf(stderr, "This program has no arguments\n");
+        exit(1);
+    }
+
+    /* Initialize our error environment variable */
+    xmlrpc_env_init(&env);
+
+    /* Required before any use of Xmlrpc-c client library: */
+    xmlrpc_client_setup_global_const(&env);
+    die_if_fault_occurred(&env);
+
+    xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0,
+                         &clientP);
+    die_if_fault_occurred(&env);
+
+    for (adder = 0; adder < 3; ++adder) {
+        printf("Making XMLRPC call to server url '%s' method '%s' "
+               "to request the sum "
+               "of 5 and %d...\n", serverUrl, methodName, adder);
+
+        /* request the remote procedure call */
+        xmlrpc_client_start_rpcf(&env, clientP, serverUrl, methodName,
+                                  handle_sample_add_response, NULL,
+                                  "(ii)", (xmlrpc_int32) 5, adder);
+        die_if_fault_occurred(&env);
+    }
+    
+    printf("RPCs all requested.  Waiting for & handling responses...\n");
+
+    /* Wait for all RPCs to be done.  With some transports, this is also
+       what causes them to go.
+    */
+    xmlrpc_client_event_loop_finish(clientP);
+
+    printf("All RPCs finished.\n");
+
+    xmlrpc_client_destroy(clientP);
+
+    return 0;
+}
diff --git a/examples/xmlrpc_inetd_server.c b/examples/xmlrpc_inetd_server.c
new file mode 100644 (file)
index 0000000..fd7b7df
--- /dev/null
@@ -0,0 +1,106 @@
+/* A simple standalone XML-RPC server based on Abyss that processes a
+   single RPC from an existing TCP connection on Standard Input.
+
+   A typical example of where this would be useful is with an Inetd
+   "super server."
+
+   xmlrpc_sample_add_server.c is a server that does the same thing,
+   but you give it a TCP port number and it listens for TCP connecitons
+   and processes RPCs ad infinitum.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/abyss.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h"  /* information about this build environment */
+
+
+static void
+setupSignalHandlers(void) {
+
+    /* In UNIX, when you try to write to a socket that has been closed
+       from the other end, your write fails, but you also get a SIGPIPE
+       signal.  That signal will kill you before you even have a chance
+       to see the write fail unless you catch, block, or ignore it.
+       If a client should connect to us and then disconnect before we've
+       sent our response, we see this socket-closed behavior.  We
+       obviously don't want to die just because a client didn't complete
+       an RPC, so we ignore SIGPIPE.
+    */
+    struct sigaction mysigaction;
+    
+    sigemptyset(&mysigaction.sa_mask);
+    mysigaction.sa_flags = 0;
+    mysigaction.sa_handler = SIG_IGN;
+    sigaction(SIGPIPE, &mysigaction, NULL);
+}
+
+
+
+static xmlrpc_value *
+sample_add(xmlrpc_env *   const envP, 
+           xmlrpc_value * const paramArrayP,
+           void *         const userData ATTR_UNUSED) {
+    
+    xmlrpc_int x, y, z;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+    if (envP->fault_occurred)
+        return NULL;
+
+    /* Add our two numbers. */
+    z = x + y;
+
+    /* Return our result. */
+    return xmlrpc_build_value(envP, "i", z);
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv) {
+
+    TServer abyssServer;
+    xmlrpc_registry * registryP;
+    xmlrpc_env env;
+
+    if (argc-1 != 0) {
+        fprintf(stderr, "There are no arguments.  You must supply a "
+                "bound socket on which to listen for client connections "
+                "as Standard Input\n");
+        if (argv) {} /* silence unused parameter warning */
+        exit(1);
+    }
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "sample.add", &sample_add, NULL);
+
+    ServerCreateNoAccept(&abyssServer, "XmlRpcServer", NULL, NULL);
+    
+    xmlrpc_server_abyss_set_handlers(&abyssServer, registryP);
+
+    setupSignalHandlers();
+
+    ServerRunConn(&abyssServer, STDIN_FILENO);
+        /* This reads the HTTP POST request from Standard Input and
+           executes the indicated RPC.
+        */
+
+    ServerFree(&abyssServer);
+
+    return 0;
+}
diff --git a/examples/xmlrpc_loop_server.c b/examples/xmlrpc_loop_server.c
new file mode 100644 (file)
index 0000000..239d59b
--- /dev/null
@@ -0,0 +1,134 @@
+/* A simple standalone XML-RPC server based on Abyss that contains a
+   simple one-thread request processing loop.  
+
+   xmlrpc_sample_add_server.c is a server that does the same thing, but
+   does it by running a full Abyss daemon in the background, so it has
+   less control over how the requests are served.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/abyss.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h"  /* information about this build environment */
+
+
+static void
+setupSignalHandlers(void) {
+
+    /* In UNIX, when you try to write to a socket that has been closed
+       from the other end, your write fails, but you also get a SIGPIPE
+       signal.  That signal will kill you before you even have a chance
+       to see the write fail unless you catch, block, or ignore it.
+       If a client should connect to us and then disconnect before we've
+       sent our response, we see this socket-closed behavior.  We
+       obviously don't want to die just because a client didn't complete
+       an RPC, so we ignore SIGPIPE.
+    */
+    struct sigaction mysigaction;
+    
+    sigemptyset(&mysigaction.sa_mask);
+    mysigaction.sa_flags = 0;
+    mysigaction.sa_handler = SIG_IGN;
+    sigaction(SIGPIPE, &mysigaction, NULL);
+}
+
+
+
+static xmlrpc_value *
+sample_add(xmlrpc_env *   const envP, 
+           xmlrpc_value * const paramArrayP,
+           void *         const userData ATTR_UNUSED) {
+    
+    xmlrpc_int x, y, z;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+    if (envP->fault_occurred)
+        return NULL;
+
+    /* Add our two numbers. */
+    z = x + y;
+
+    /* Return our result. */
+    return xmlrpc_build_value(envP, "i", z);
+}
+
+
+
+static xmlrpc_server_shutdown_fn requestShutdown;
+
+static void
+requestShutdown(xmlrpc_env * const envP,
+                void *       const context,
+                const char * const comment) {
+
+    /* You make this run by executing the system method
+       'system.shutdown'.  This function is registered in the method
+       registry as the thing to call for that.
+    */
+    int * const terminationRequestedP = context;
+
+    xmlrpc_env_init(envP);
+
+    fprintf(stderr, "Termination requested: %s\n", comment);
+    
+    *terminationRequestedP = 1;
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv) {
+
+    TServer abyssServer;
+    xmlrpc_registry * registryP;
+    xmlrpc_env env;
+    int terminationRequested;  /* A boolean value */
+
+    if (argc-1 != 1) {
+        fprintf(stderr, "You must specify 1 argument:  The TCP port number "
+                "on which to listen for XML-RPC calls.  "
+                "You specified %d.\n",  argc-1);
+        exit(1);
+    }
+    
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "sample.add", &sample_add, NULL);
+
+    xmlrpc_registry_set_shutdown(registryP,
+                                 &requestShutdown, &terminationRequested);
+
+    ServerCreate(&abyssServer, "XmlRpcServer", atoi(argv[1]), NULL, NULL);
+    
+    xmlrpc_server_abyss_set_handlers(&abyssServer, registryP);
+
+    ServerInit(&abyssServer);
+
+    setupSignalHandlers();
+
+    terminationRequested = 0;
+
+    while (!terminationRequested) {
+        printf("Waiting for next RPC...\n");
+
+        ServerRunOnce(&abyssServer);
+            /* This waits for the next connection, accepts it, reads the
+               HTTP POST request, executes the indicated RPC, and closes
+               the connection.
+            */
+    }
+
+    ServerFree(&abyssServer);
+    
+    return 0;
+}
diff --git a/examples/xmlrpc_sample_add_client.c b/examples/xmlrpc_sample_add_client.c
new file mode 100644 (file)
index 0000000..100d8fc
--- /dev/null
@@ -0,0 +1,76 @@
+/* A simple synchronous XML-RPC client written in C, as an example of
+   an Xmlrpc-c client.  This invokes the sample.add procedure that the
+   Xmlrpc-c example server.c server provides.  I.e. it adds to numbers
+   together, the hard way.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+
+#include "config.h"  /* information about this build environment */
+
+#define NAME "Xmlrpc-c Test Client"
+#define VERSION "1.0"
+
+static void 
+die_if_fault_occurred (xmlrpc_env *env) {
+    if (env->fault_occurred) {
+        fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
+                env->fault_string, env->fault_code);
+        exit(1);
+    }
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv ATTR_UNUSED) {
+
+    xmlrpc_env env;
+    xmlrpc_value *result;
+    xmlrpc_int32 sum;
+    char * const serverUrl = "http://localhost:8080/RPC2";
+    char * const methodName = "sample.add";
+
+    if (argc-1 > 0) {
+        fprintf(stderr, "This program has no arguments\n");
+        exit(1);
+    }
+
+    /* Initialize our error-handling environment. */
+    xmlrpc_env_init(&env);
+
+    /* Start up our XML-RPC client library. */
+    xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0);
+    die_if_fault_occurred(&env);
+
+    printf("Making XMLRPC call to server url '%s' method '%s' "
+           "to request the sum "
+           "of 5 and 7...\n", serverUrl, methodName);
+
+    /* Make the remote procedure call */
+    result = xmlrpc_client_call(&env, serverUrl, methodName,
+                                "(ii)", (xmlrpc_int32) 5, (xmlrpc_int32) 7);
+    die_if_fault_occurred(&env);
+    
+    /* Get our sum and print it out. */
+    xmlrpc_read_int(&env, result, &sum);
+    die_if_fault_occurred(&env);
+    printf("The sum is %d\n", sum);
+    
+    /* Dispose of our result value. */
+    xmlrpc_DECREF(result);
+
+    /* Clean up our error-handling environment. */
+    xmlrpc_env_clean(&env);
+    
+    /* Shutdown our XML-RPC client library. */
+    xmlrpc_client_cleanup();
+
+    return 0;
+}
+
diff --git a/examples/xmlrpc_sample_add_server.c b/examples/xmlrpc_sample_add_server.c
new file mode 100644 (file)
index 0000000..3dde122
--- /dev/null
@@ -0,0 +1,80 @@
+/* A simple standalone XML-RPC server written in C. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h"  /* information about this build environment */
+
+static xmlrpc_value *
+sample_add(xmlrpc_env *   const env, 
+           xmlrpc_value * const param_array, 
+           void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_int32 x, y, z;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
+    if (env->fault_occurred)
+        return NULL;
+
+    /* Add our two numbers. */
+    z = x + y;
+
+    /* Sometimes, make it look hard (so client can see what it's like
+       to do an RPC that takes a while).
+    */
+    if (y == 1)
+        sleep(2);
+
+    /* Return our result. */
+    return xmlrpc_build_value(env, "i", z);
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv) {
+
+    xmlrpc_server_abyss_parms serverparm;
+    xmlrpc_registry * registryP;
+    xmlrpc_env env;
+
+    if (argc-1 != 1) {
+        fprintf(stderr, "You must specify 1 argument:  The TCP port "
+                "number on which the server will accept connections "
+                "for RPCs.  You specified %d arguments.\n",  argc-1);
+        exit(1);
+    }
+    
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "sample.add", &sample_add, NULL);
+
+    /* In the modern form of the Abyss API, we supply parameters in memory
+       like a normal API.  We select the modern form by setting
+       config_file_name to NULL: 
+    */
+    serverparm.config_file_name = NULL;
+    serverparm.registryP        = registryP;
+    serverparm.port_number      = atoi(argv[1]);
+    serverparm.log_file_name    = "/tmp/xmlrpc_log";
+
+    printf("Running XML-RPC server...\n");
+
+    xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));
+
+    /* xmlrpc_server_abyss() never returns */
+
+    return 0;
+}
diff --git a/examples/xmlrpc_sample_add_server_cgi.c b/examples/xmlrpc_sample_add_server_cgi.c
new file mode 100644 (file)
index 0000000..18374a1
--- /dev/null
@@ -0,0 +1,57 @@
+/* A simple standalone XML-RPC server written in C. */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_cgi.h>
+
+#include "config.h"  /* information about this build environment */
+
+static xmlrpc_value *
+sample_add(xmlrpc_env *   const env, 
+           xmlrpc_value * const param_array, 
+           void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_int32 x, y, z;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
+    if (env->fault_occurred)
+        return NULL;
+
+    /* Add our two numbers. */
+    z = x + y;
+
+    /* Return our result. */
+    return xmlrpc_build_value(env, "i", z);
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv) {
+
+    xmlrpc_registry * registryP;
+    xmlrpc_env env;
+
+    if (argc-1 > 0 && argv==argv) {
+        fprintf(stderr, "There are no arguments to a CGI script\n");
+        exit(1);
+    }
+
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "sample.add", &sample_add, NULL);
+
+    xmlrpc_server_cgi_process_call(registryP);
+
+    xmlrpc_registry_free(registryP);
+
+    return 0;
+}
diff --git a/examples/xmlrpc_sample_add_server_w32httpsys.c b/examples/xmlrpc_sample_add_server_w32httpsys.c
new file mode 100644 (file)
index 0000000..f794f19
--- /dev/null
@@ -0,0 +1,190 @@
+/* Copyright (C) 2005 by Steven A. Bone, sbone@pobox.com. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+/* COMPILATION NOTE:
+   Note that the Platform SDK headers and
+   link libraries for Windows XP SP2 or newer are required to compile
+   xmlrpc-c for this module.  If you are not using this server, it is 
+   safe to exclude the xmlrpc_server_w32httpsys.c file from the xmlrpc
+   project and these dependencies will not be required.  You can get the 
+   latest platform SDK at 
+   http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+   Be sure after installation to choose the program to "register the PSDK
+   directories with Visual Studio" so the newer headers are found.
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_w32httpsys.h>
+
+
+/*  SECURITY NOTE: Using HTTP Authorization
+
+The current implementation of HTTP Authorization in the win32httpsys
+server only uses basic Authorization.  This means the userid and password
+is sent in clear-text over the network (Technically, it is Base64 encoded,
+but this is essentially clear text).  This method is not secure, as it
+can be captured and decoded.  The use of HTTP Basic Authorization with SSL
+is considered much more secure.  See the note below for configuring SSL
+support.
+*/
+
+
+/*  
+HOWTO: Configure SSL for the XMLRPC-C Server
+
+To use SSL you need an SSL certificate.  For testing purposes,
+it is possible to create a self-signed SSL certificate.  To do so,
+you must download the IIS 6.0 Resource Kit tools.  The current
+URL to get the download link is http://support.microsoft.com/kb/840671
+We will be using the SelfSSL version 1.0 from this toolkit for
+this example.  The other tool you will need is httpcfg.exe, which
+can be compiled from the sources in the Windows XP SP2 (or newer) Platform SDK,
+or downloaded as part of the Windows XP SP2 Support Tools at the following URL:
+http://www.microsoft.com/downloads/details.aspx?FamilyID=49ae8576-9bb9-4126-9761-ba8011fabf38&displaylang=en
+The last assumption is that this procedure is being done on the machine that is
+hosting the XMLRPC-C server application.
+
+1) Make sure that IIS is installed, and you are running at least Windows XP SP2
+or Windows Server 2003.  WARNING: This process will replace any existing IIS SSL
+certificates currently installed.
+
+2) In a command prompt, navigate to the directory of the
+IIS Support Tools where the selfssl program exists (usually 
+C:\Program Files\IIS Resources\SelfSSL).  Assuming (as we are for this example)
+that we are going to run on port 8443, use the following command line (see the
+documentation for all the flags):
+
+selfssl /T /V:365 /P:8443
+
+3) In the Control Panel, Administrative tools, run the Internet Information Services
+program.  Drill down to the Default Web Site.  Right-click it and choose Properties.
+On the "Web Site" tab, you will notice that the SSL port is now set to 8443.  Change
+it back to 443.  On the Directory Security tab, pick "View Certificate".  In the 
+"Details" tab, select the "Thumbprint" line.  The edit box below the listbox will
+display a series of hex numbers.  Copy these to the clipboard and paste into notepad.
+OK yourself out of the IIS program.
+
+4) Remove all the spaces in the hex string so you are left with a string with no spaces.
+This is your SSL Thumbprint hash which you will need in the next step.
+
+5) At your command prompt, navigate to the support tools directory (or the location
+where you built httpcfg.exe) - usually C:\Program Files\Support Tools.  Run the following
+command line, replacing both the brackets and text with your thumbprint hash from step 4 above:
+
+httpcfg.exe set ssl -i 0.0.0.0:8443 -h <replace with thumbprint hash> -g "{2bb50d9c-7f6a-4d6f-873d-5aee7fb43290}" -c "MY" -t "" -n ""
+
+6) You can check the setup by performing a "httpcfg.exe query ssl" if you wish.
+
+7) Modify the example server code below to use SSL.  Set the xmlrpc_server_httpsys_parms.useSSL
+to '1' and the xmlrpc_server_httpsys_parms.portNum to be '8443'.  You can test the server by using 
+IE to browse to the URL https://127.0.0.1:8443/rpc2.  An error 405 (Resource not allowed) is the 
+expected result if everything is working properly.
+
+NOTE: Testing clients with a 'test' or not real SSL certificate involves changing some of the default
+code in the client samples, as by default the transports will fail if there are any issues with the
+certificate.  The WinInet transport as of 1.2 has a transport-specific setting to allow 
+invalid SSL certificates.  See the libxmlrpc_client.html documentation for more details.
+
+NOTE: Failure to follow all the steps listed above correctly will result in no application
+errors, event log messages, or HTTP.SYS log messages indicating failure or the cause.  If
+anyone can provide information on debugging SSL certificate issues in HTTP.SYS, please
+submit to us!
+*/
+
+
+static xmlrpc_value *
+sample_add(xmlrpc_env *   const env, 
+           xmlrpc_value * const param_array, 
+           void *         const user_data ) {
+
+    xmlrpc_int32 x, y, z;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
+    if (env->fault_occurred)
+        return NULL;
+
+    /* Add our two numbers. */
+    z = x + y;
+
+    /* Return our result. */
+    return xmlrpc_build_value(env, "i", z);
+}
+
+static void handleAuthorization(
+               xmlrpc_env * envP,
+        char * userid,
+        char * password)
+{
+       if (strcmp(userid,"jrandom")==0 && strcmp(password,"secret")==0)
+               return;
+
+       xmlrpc_env_set_fault( envP, XMLRPC_REQUEST_REFUSED_ERROR, 
+                                                 "Username and/or password do not match.");
+}
+
+int __cdecl wmain( int argc, wchar_t * argv[])
+{
+       xmlrpc_server_httpsys_parms serverparm;
+    xmlrpc_registry * registryP;
+    xmlrpc_env env;
+
+       xmlrpc_env_init(&env);
+
+       registryP = xmlrpc_registry_new(&env);
+
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "sample.add", &sample_add, NULL);
+
+    wprintf(L"Starting XML-RPC server...\n");
+
+       //Sets the port number we are listening on
+       serverparm.portNum=8080;
+
+       //if this is set, we will use the authorization function
+       serverparm.authfn=NULL;
+       //serverparm.authfn=&handleAuthorization;
+
+       //set the logging level and log file
+       serverparm.logLevel=2;
+       serverparm.logFile="C:\\httpsysserverlog.txt";
+
+       //set the use of SSL
+       serverparm.useSSL=0;
+
+    serverparm.registryP = registryP;
+
+    xmlrpc_server_httpsys(&env, &serverparm, XMLRPC_HSSIZE(authfn));
+
+       wprintf(L"Stopping XML-RPC server...\n");
+
+       xmlrpc_registry_free(registryP);
+       xmlrpc_env_clean(&env);
+
+    return 0;
+}
diff --git a/examples/xmlrpc_server_validatee.c b/examples/xmlrpc_server_validatee.c
new file mode 100644 (file)
index 0000000..6d55e5f
--- /dev/null
@@ -0,0 +1,402 @@
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+
+/*============================================================================
+                              xmlrpc_server_validatee
+==============================================================================
+
+  This program runs an XMLRPC server, using the Xmlrpc-c libraries.
+
+  The server implements the methods that the Userland Validator1 test suite
+  invokes, which are supposed to exercise a broad range of XMLRPC server
+  function.
+
+  Coments here used to say you could get information about Validator1
+  from <http://validator.xmlrpc.com/>, but as of 2004.09.25, there's nothing
+  there (there's a web server, but it is not configured to serve that
+  particular URL).
+
+============================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h"  /* information about this build environment */
+
+#define RETURN_IF_FAULT(env) \
+    do { \
+        if ((env)->fault_occurred) \
+            return NULL; \
+    } while (0)
+        
+
+/*=========================================================================
+**  validator1.arrayOfStructsTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+array_of_structs(xmlrpc_env *   const envP, 
+                 xmlrpc_value * const param_array, 
+                 void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_value * array;
+    xmlrpc_value * retval;
+
+    xmlrpc_decompose_value(envP, param_array, "(A)", &array);
+    if (envP->fault_occurred)
+        retval = NULL;
+    else {
+        /* Add up all the struct elements named "curly". */
+        size_t size;
+        size = xmlrpc_array_size(envP, array);
+        if (envP->fault_occurred)
+            retval = NULL;
+        else {
+            unsigned int sum;
+            unsigned int i;
+            sum = 0;
+            for (i = 0; i < size && !envP->fault_occurred; ++i) {
+                xmlrpc_value * strct;
+                strct = xmlrpc_array_get_item(envP, array, i);
+                if (!envP->fault_occurred) {
+                    xmlrpc_int32 curly;
+                    xmlrpc_decompose_value(envP, strct, "{s:i,*}", 
+                                           "curly", &curly);
+                    if (!envP->fault_occurred)
+                        sum += curly;
+                }
+            }
+            xmlrpc_DECREF(array);
+            if (envP->fault_occurred)
+                retval = NULL;
+            else
+                retval = xmlrpc_build_value(envP, "i", sum);
+        }
+    }
+    return retval;
+}
+
+
+/*=========================================================================
+**  validator1.countTheEntities
+**=========================================================================
+*/
+
+static xmlrpc_value *
+count_entities(xmlrpc_env *   const env, 
+               xmlrpc_value * const param_array, 
+               void *         const user_data ATTR_UNUSED) {
+    const char *str;
+    size_t len, i;
+    xmlrpc_int32 left, right, amp, apos, quote;
+
+    xmlrpc_decompose_value(env, param_array, "(s#)", &str, &len);
+    RETURN_IF_FAULT(env);
+
+    left = right = amp = apos = quote = 0;
+    for (i = 0; i < len; i++) {
+        switch (str[i]) {
+        case '<': left++; break;
+        case '>': right++; break;
+        case '&': amp++; break;
+        case '\'': apos++; break;
+        case '\"': quote++; break;
+        default: break;
+        }
+    }
+    free((void*)str);
+
+    return xmlrpc_build_value(env, "{s:i,s:i,s:i,s:i,s:i}",
+                              "ctLeftAngleBrackets", left,
+                              "ctRightAngleBrackets", right,
+                              "ctAmpersands", amp,
+                              "ctApostrophes", apos,
+                              "ctQuotes", quote);
+}
+
+
+
+/*=========================================================================
+**  validator1.easyStructTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+easy_struct(xmlrpc_env *   const env, 
+            xmlrpc_value * const param_array,
+            void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_int32 larry, moe, curly;
+
+    /* Parse our argument array and get the stooges. */
+    xmlrpc_decompose_value(env, param_array, "({s:i,s:i,s:i,*})",
+                           "larry", &larry,
+                           "moe", &moe,
+                           "curly", &curly);
+    RETURN_IF_FAULT(env);
+
+    /* Return our result. */
+    return xmlrpc_build_value(env, "i", larry + moe + curly);
+}
+
+
+/*=========================================================================
+**  validator1.echoStructTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+echo_struct(xmlrpc_env *   const env, 
+            xmlrpc_value * const param_array, 
+            void *         const user_data ATTR_UNUSED) {
+    xmlrpc_value *s;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(env, param_array, "(S)", &s);
+    RETURN_IF_FAULT(env);
+    
+    return s;  /* We transfer our reference on 's' to Caller */
+}
+
+
+/*=========================================================================
+**  validator1.manyTypesTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+many_types(xmlrpc_env *   const env ATTR_UNUSED, 
+           xmlrpc_value * const param_array, 
+           void *         const user_data ATTR_UNUSED) {
+
+    /* Create another reference to our argument array and return it as is. */
+    xmlrpc_INCREF(param_array);
+    return param_array;
+}
+
+
+/*=========================================================================
+**  validator1.moderateSizeArrayCheck
+**=========================================================================
+*/
+
+static void
+concatenate(xmlrpc_env *    const envP,
+            const char *    const str1,
+            size_t          const str1_len,
+            const char *    const str2,
+            size_t          const str2_len,
+            xmlrpc_value ** const resultP) {
+
+    /* Concatenate the two strings. */
+
+    char * buffer;
+
+    buffer = (char*) malloc(str1_len + str2_len);
+    if (!buffer) {
+        xmlrpc_env_set_fault(envP, 1, 
+                             "Couldn't allocate concatenated string");
+    } else {
+        memcpy(buffer, str1, str1_len);
+        memcpy(&buffer[str1_len], str2, str2_len);
+        *resultP = xmlrpc_build_value(envP, "s#", 
+                                      buffer, str1_len + str2_len);
+        free(buffer);
+    }
+}
+
+
+
+static xmlrpc_value *
+moderate_array(xmlrpc_env *   const envP, 
+               xmlrpc_value * const param_array, 
+               void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_value * retval;
+    xmlrpc_value * arrayP;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(envP, param_array, "(A)", &arrayP);
+    if (!envP->fault_occurred) {
+        int const size = xmlrpc_array_size(envP, arrayP);
+        if (!envP->fault_occurred) {
+            /* Get our first string. */
+            xmlrpc_value * const firstItemP =
+                xmlrpc_array_get_item(envP, arrayP, 0);
+            if (!envP->fault_occurred) {
+                const char * str1;
+                size_t str1_len;
+                xmlrpc_read_string_lp(envP, firstItemP, &str1_len, &str1);
+                if (!envP->fault_occurred) {
+                    /* Get our last string. */
+                    xmlrpc_value * const lastItemP =
+                        xmlrpc_array_get_item(envP, arrayP, size - 1);
+                    if (!envP->fault_occurred) {
+                        const char * str2;
+                        size_t str2_len;
+                        xmlrpc_read_string_lp(envP, lastItemP,
+                                              &str2_len, &str2);
+                        if (!envP->fault_occurred) {
+                            concatenate(envP, str1, str1_len, str2, str2_len,
+                                        &retval);
+                            free((char*)str2);
+                        }
+                    }
+                    free((char*)str1);
+                }
+            }
+        }
+        xmlrpc_DECREF(arrayP);
+    }
+    return retval;
+}
+
+
+/*=========================================================================
+**  validator1.nestedStructTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+nested_struct(xmlrpc_env *   const envP,
+              xmlrpc_value * const param_array, 
+              void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_value * yearsP;
+    xmlrpc_value * retval;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(envP, param_array, "(S)", &yearsP);
+    if (envP->fault_occurred)
+        retval = NULL;
+    else {
+        /* Get values of larry, moe and curly for 2000-04-01. */
+        xmlrpc_int32 larry, moe, curly;
+        xmlrpc_decompose_value(envP, yearsP,
+                               "{s:{s:{s:{s:i,s:i,s:i,*},*},*},*}",
+                               "2000", "04", "01",
+                               "larry", &larry,
+                               "moe", &moe,
+                               "curly", &curly);               
+        if (envP->fault_occurred)
+            retval = NULL;
+        else
+            retval = xmlrpc_build_value(envP, "i", larry + moe + curly);
+
+        xmlrpc_DECREF(yearsP);
+    }
+    return retval;
+}
+
+
+/*=========================================================================
+**  validator1.simpleStructReturnTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+struct_return(xmlrpc_env *   const env, 
+              xmlrpc_value * const param_array, 
+              void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_int32 i;
+
+    xmlrpc_decompose_value(env, param_array, "(i)", &i);
+    RETURN_IF_FAULT(env);
+
+    return xmlrpc_build_value(env, "{s:i,s:i,s:i}",
+                              "times10", (xmlrpc_int32) i * 10,
+                              "times100", (xmlrpc_int32) i * 100,
+                              "times1000", (xmlrpc_int32) i * 1000);
+}
+
+
+/*=========================================================================
+**  main
+**=========================================================================
+*/
+
+int main(int           const argc, 
+         const char ** const argv) {
+
+    xmlrpc_server_abyss_parms serverparm;
+    xmlrpc_registry * registryP;
+    xmlrpc_env env;
+
+    if (argc-1 != 1) {
+        fprintf(stderr, "You must specify 1 argument:  The TCP port "
+                "number on which the server will accept connections "
+                "for RPCs.  You specified %d arguments.\n",  argc-1);
+        exit(1);
+    }
+
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "validator1.arrayOfStructsTest", 
+        &array_of_structs, NULL);
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "validator1.countTheEntities", 
+        &count_entities, NULL);
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "validator1.easyStructTest", 
+        &easy_struct, NULL);
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "validator1.echoStructTest", 
+        &echo_struct, NULL);
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "validator1.manyTypesTest", 
+        &many_types, NULL);
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "validator1.moderateSizeArrayCheck", 
+        &moderate_array, NULL);
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "validator1.nestedStructTest", 
+        &nested_struct, NULL);
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "validator1.simpleStructReturnTest", 
+        &struct_return, NULL);
+
+    serverparm.config_file_name = NULL;
+    serverparm.registryP = registryP;
+    serverparm.port_number = atoi(argv[1]);
+    serverparm.log_file_name = NULL;
+
+    printf("Running XML-RPC server...\n");
+
+    xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));
+
+    /* This never gets executed. */
+    return 0;
+}
diff --git a/examples/xmlrpc_socket_server.c b/examples/xmlrpc_socket_server.c
new file mode 100644 (file)
index 0000000..b20ce15
--- /dev/null
@@ -0,0 +1,91 @@
+/* A simple standalone XML-RPC server written in C as an example of use of
+   the Xmlrpc-c libraries.
+
+   This example expects an already bound socket on Standard Input, ready to
+   be listened on for client connections.  Also see xmlrpc_sample_add_server,
+   which is the same thing, except you tell it a TCP port number and it
+   creates the socket itself.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/server_abyss.h>
+
+#include "config.h"  /* information about this build environment */
+
+static xmlrpc_value *
+sample_add(xmlrpc_env *   const env, 
+           xmlrpc_value * const param_array, 
+           void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_int32 x, y, z;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
+    if (env->fault_occurred)
+        return NULL;
+
+    /* Add our two numbers. */
+    z = x + y;
+
+    /* Sometimes, make it look hard (so client can see what it's like
+       to do an RPC that takes a while).
+    */
+    if (y == 1)
+        sleep(2);
+
+    /* Return our result. */
+    return xmlrpc_build_value(env, "i", z);
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv) {
+
+    xmlrpc_server_abyss_parms serverparm;
+    xmlrpc_registry * registryP;
+    xmlrpc_env env;
+
+    if (argc-1 != 0) {
+        fprintf(stderr, "There are no arguments.  You must supply a "
+                "bound socket on which to listen for client connections "
+                "as Standard Input\n");
+        if (argv) {} /* silence unused parameter warning */
+        exit(1);
+    }
+    
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+
+    xmlrpc_registry_add_method(
+        &env, registryP, NULL, "sample.add", &sample_add, NULL);
+
+    /* In the modern form of the Abyss API, we supply parameters in memory
+       like a normal API.  We select the modern form by setting
+       config_file_name to NULL: 
+    */
+    serverparm.config_file_name   = NULL;
+    serverparm.registryP          = registryP;
+    serverparm.log_file_name      = "/tmp/xmlrpc_log";
+    serverparm.keepalive_timeout  = 0;
+    serverparm.keepalive_max_conn = 0;
+    serverparm.timeout            = 0;
+    serverparm.dont_advertise     = FALSE;
+    serverparm.socket_bound       = TRUE;
+    serverparm.socket_handle      = STDIN_FILENO;
+
+    printf("Running XML-RPC server...\n");
+
+    xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(socket_handle));
+
+    return 0;
+}
diff --git a/include/Makefile b/include/Makefile
new file mode 100644 (file)
index 0000000..6c76478
--- /dev/null
@@ -0,0 +1,79 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/..
+endif
+SUBDIR = src
+BUILDDIR = $(SRCDIR)
+VPATH = .:$(SRCDIR)
+
+include $(BUILDDIR)/Makefile.config
+
+default: all
+
+all: xmlrpc-c/config.h
+
+xmlrpc-c/config.h:
+       echo "#define XMLRPC_HAVE_WCHAR $(HAVE_WCHAR_H_DEFINE)" >$@
+
+
+HEADERS_TO_INSTALL = \
+  xmlrpc-c/config.h \
+  xmlrpc-c/util.h \
+  xmlrpc-c/base.h \
+  xmlrpc-c/abyss.h \
+  xmlrpc-c/server.h \
+  xmlrpc-c/server_abyss.h \
+  xmlrpc-c/server_w32httpsys.h \
+  xmlrpc-c/oldxmlrpc.h \
+
+ifeq ($(ENABLE_CPLUSPLUS),yes)
+  HEADERS_TO_INSTALL += \
+    xmlrpc-c/oldcppwrapper.hpp \
+    xmlrpc-c/girerr.hpp \
+    xmlrpc-c/girmem.hpp \
+    xmlrpc-c/base.hpp \
+    xmlrpc-c/timeout.hpp \
+    xmlrpc-c/xml.hpp \
+    xmlrpc-c/registry.hpp \
+    xmlrpc-c/server_abyss.hpp \
+
+endif
+
+HEADERINST_PREFIX = /xmlrpc-c
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  HEADERS_TO_INSTALL += \
+    xmlrpc-c/client.h \
+    xmlrpc-c/transport.h \
+    xmlrpc-c/client_global.h \
+
+  ifeq ($(ENABLE_CPLUSPLUS),yes)
+    HEADERS_TO_INSTALL += \
+      xmlrpc-c/client.hpp \
+      xmlrpc-c/client_transport.hpp \
+      xmlrpc-c/client_simple.hpp \
+
+  endif
+endif
+ifeq ($(ENABLE_CGI_SERVER),yes)
+  HEADERS_TO_INSTALL += xmlrpc-c/server_cgi.h
+endif
+
+default: all
+
+all:
+
+.PHONY: install
+install: install-common
+
+.PHONY: clean distclean dep
+clean:
+distclean:
+       rm -f xmlrpc-c/config.h
+
+.PHONY: check
+check:
+
+.PHONY: dep
+dep:
+
+include $(SRCDIR)/Makefile.common
diff --git a/include/xmlrpc-c/.cvsignore b/include/xmlrpc-c/.cvsignore
new file mode 100644 (file)
index 0000000..0e56cf2
--- /dev/null
@@ -0,0 +1 @@
+config.h
diff --git a/include/xmlrpc-c/abyss.h b/include/xmlrpc-c/abyss.h
new file mode 100644 (file)
index 0000000..d9aeb9a
--- /dev/null
@@ -0,0 +1,527 @@
+/*****************************************************************************
+                                 abyss.h
+******************************************************************************
+
+  This file is the interface header for the Abyss HTTP server component of
+  XML-RPC For C/C++ (Xmlrpc-c).
+
+  The Abyss component of Xmlrpc-c is based on the independently developed
+  and distributed Abyss web server package from 2001.
+
+  Copyright information is at the end of the file.
+****************************************************************************/
+
+#ifndef _ABYSS_H_
+#define _ABYSS_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+#ifdef WIN32
+#include "xmlrpc_config.h"
+#else
+#include <inttypes.h>
+#endif
+
+/****************************************************************************
+  STUFF FOR THE OUTER CONTROL PROGRAM TO USE
+****************************************************************************/
+
+typedef int abyss_bool;
+
+/*********************************************************************
+** MIMEType
+*********************************************************************/
+
+typedef struct MIMEType MIMEType;
+
+MIMEType *
+MIMETypeCreate(void);
+
+void
+MIMETypeDestroy(MIMEType * const MIMETypeP);
+
+void
+MIMETypeInit(void);
+
+void
+MIMETypeTerm(void);
+
+abyss_bool
+MIMETypeAdd2(MIMEType *   const MIMETypeP,
+             const char * const type,
+             const char * const ext);
+
+abyss_bool
+MIMETypeAdd(const char * const type,
+            const char * const ext);
+
+
+enum abyss_foreback {ABYSS_FOREGROUND, ABYSS_BACKGROUND};
+
+
+typedef struct _TSocket TSocket;
+
+/* TOsSocket is the type of a conventional socket offered by our OS.
+   This is for backward compatibility; everyone should use TSocket
+   sockets today.
+*/
+#ifdef WIN32
+void
+SocketWinCreate(TSocket ** const socketPP);
+
+void
+SocketWinCreateWinsock(SOCKET     const winsock,
+                       TSocket ** const socketPP);
+
+typedef SOCKET TOsSocket;
+
+#else  /* WIN32 */
+
+void
+SocketUnixCreate(TSocket ** const socketPP);
+
+void
+SocketUnixCreateFd(int        const fd,
+                   TSocket ** const socketPP);
+
+typedef int TOsSocket;
+#endif  /* WIN32 */
+
+void
+SocketDestroy(TSocket * const socketP);
+
+
+typedef struct {
+    /* Before Xmlrpc-c 1.04, the internal server representation,
+       struct _TServer, was exposed to users and was the only way to
+       set certain parameters of the server.  Now, use the (new)
+       ServerSet...() functions.  Use the HAVE_ macros to determine
+       which method you have to use.
+    */
+    struct _TServer * srvP;
+} TServer;
+
+typedef struct _TSession TSession;
+
+abyss_bool
+ServerCreate(TServer *    const serverP,
+             const char * const name,
+             uint16_t     const port,
+             const char * const filespath,
+             const char * const logfilename);
+
+abyss_bool
+ServerCreateSocket(TServer *    const serverP,
+                   const char * const name,
+                   TOsSocket    const socketFd,
+                   const char * const filespath,
+                   const char * const logfilename);
+
+#define HAVE_SERVER_CREATE_SOCKET_2
+void
+ServerCreateSocket2(TServer *     const serverP,
+                    TSocket *     const socketP,
+                    const char ** const errorP);
+
+abyss_bool
+ServerCreateNoAccept(TServer *    const serverP,
+                     const char * const name,
+                     const char * const filespath,
+                     const char * const logfilename);
+
+void
+ServerFree(TServer * const serverP);
+
+void
+ServerSetName(TServer *    const serverP,
+              const char * const name);
+
+void
+ServerSetFilesPath(TServer *    const serverP,
+                   const char * const filesPath);
+
+void
+ServerSetLogFileName(TServer *    const serverP,
+                     const char * const logFileName);
+
+#define HAVE_SERVER_SET_KEEPALIVE_TIMEOUT 1
+void
+ServerSetKeepaliveTimeout(TServer * const serverP,
+                          uint32_t  const keepaliveTimeout);
+
+#define HAVE_SERVER_SET_KEEPALIVE_MAX_CONN 1
+void
+ServerSetKeepaliveMaxConn(TServer * const serverP,
+                          uint32_t  const keepaliveMaxConn);
+
+#define HAVE_SERVER_SET_TIMEOUT 1
+void
+ServerSetTimeout(TServer * const serverP,
+                 uint32_t  const timeout);
+
+#define HAVE_SERVER_SET_ADVERTISE 1
+void
+ServerSetAdvertise(TServer *  const serverP,
+                   abyss_bool const advertise);
+
+#define HAVE_SERVER_SET_MIME_TYPE 1
+void
+ServerSetMimeType(TServer *  const serverP,
+                  MIMEType * const MIMETypeP);
+
+void
+ServerInit(TServer * const serverP);
+
+void
+ServerRun(TServer * const serverP);
+
+void
+ServerRunOnce(TServer * const serverP);
+
+/* ServerRunOnce2() is obsolete.  See user's guide. */
+void
+ServerRunOnce2(TServer *           const serverP,
+               enum abyss_foreback const foregroundBackground);
+
+void
+ServerRunConn(TServer * const serverP,
+              TOsSocket const connectedSocket);
+
+#define HAVE_SERVER_RUN_CONN_2
+void
+ServerRunConn2(TServer *     const serverP,
+               TSocket *     const connectedSocketP,
+               const char ** const errorP);
+
+void
+ServerDaemonize(TServer * const serverP);
+
+void
+ServerTerminate(TServer * const serverP);
+
+void
+ServerResetTerminate(TServer * const serverP);
+
+void
+ServerUseSigchld(TServer * const serverP);
+
+#ifndef WIN32
+void
+ServerHandleSigchld(pid_t const pid);
+#endif
+
+typedef abyss_bool (*URIHandler) (TSession *); /* deprecated */
+
+struct URIHandler2;
+
+typedef void (*initHandlerFn)(struct URIHandler2 *,
+                              abyss_bool *);
+
+typedef void (*termHandlerFn)(void *);
+
+typedef void (*handleReq2Fn)(struct URIHandler2 *,
+                             TSession *,
+                             abyss_bool *);
+
+typedef struct URIHandler2 {
+    initHandlerFn init;
+    termHandlerFn term;
+    handleReq2Fn  handleReq2;
+    URIHandler    handleReq1;  /* deprecated */
+    void *        userdata;
+} URIHandler2;
+
+void
+ServerAddHandler2(TServer *     const srvP,
+                  URIHandler2 * const handlerP,
+                  abyss_bool *  const successP);
+
+abyss_bool
+ServerAddHandler(TServer * const srvP,
+                 URIHandler const handler);
+
+void
+ServerDefaultHandler(TServer *  const srvP,
+                     URIHandler const handler);
+
+/* This is inappropriately named; it was a mistake.  But then, so is
+   having this function at all.  The config file is inappropriate for
+   an API.
+*/
+abyss_bool
+ConfReadServerFile(const char * const filename,
+                   TServer *    const srvP);
+
+void
+LogWrite(TServer *    const srvP,
+         const char * const c);
+
+/****************************************************************************
+  STUFF FOR URI HANDLERS TO USE
+****************************************************************************/
+
+typedef enum {
+    m_unknown, m_get, m_put, m_head, m_post, m_delete, m_trace, m_options
+} TMethod;
+
+typedef struct {
+    TMethod method;
+    const char * uri;
+        /* This is NOT the URI.  It is the pathname part of the URI.
+           We really should fix that and put the pathname in another
+           member.
+        */
+    const char * query;
+        /* The query part of the URI (stuff after '?') */
+    const char * host;
+        /* NOT the value of the host: header.  Rather, the name of the
+           target host (could be part of the host: value).  No port number.
+        */
+    const char * from;
+    const char * useragent;
+    const char * referer;
+    const char * requestline;
+    const char * user;
+    unsigned short port;
+    abyss_bool keepalive;
+} TRequestInfo;
+
+abyss_bool
+SessionRefillBuffer(TSession * const sessionP);
+
+size_t
+SessionReadDataAvail(TSession * const sessionP);
+
+void
+SessionGetReadData(TSession *    const sessionP, 
+                   size_t        const max, 
+                   const char ** const outStartP, 
+                   size_t *      const outLenP);
+
+void
+SessionGetRequestInfo(TSession *            const sessionP,
+                      const TRequestInfo ** const requestInfoPP);
+
+char *
+RequestHeaderValue(TSession * const sessionP,
+                   char *     const name);
+
+abyss_bool
+ResponseAddField(TSession *   const sessionP,
+                 const char * const name,
+                 const char * const value);
+
+void
+ResponseWriteStart(TSession * const sessionP);
+
+/* For backward compatibility: */
+#define ResponseWrite ResponseWriteStart
+
+abyss_bool
+ResponseWriteBody(TSession *   const sessionP,
+                  const char * const data,
+                  uint32_t     const len);
+
+abyss_bool
+ResponseWriteEnd(TSession * const sessionP);
+
+abyss_bool
+ResponseChunked(TSession * const sessionP);
+
+uint16_t
+ResponseStatusFromErrno(int const errnoArg);
+
+void
+ResponseStatus(TSession * const sessionP,
+               uint16_t   const code);
+
+void
+ResponseStatusErrno(TSession * const sessionP);
+
+abyss_bool
+ResponseContentType(TSession *   const serverP,
+                    const char * const type);
+
+abyss_bool
+ResponseContentLength(TSession * const sessionP,
+                      uint64_t   const len);
+
+void
+ResponseError(TSession * const sessionP);
+
+const char *
+MIMETypeFromExt(const char * const ext);
+
+const char *
+MIMETypeFromExt2(MIMEType *   const MIMETypeP,
+                 const char * const ext);
+
+const char *
+MIMETypeFromFileName2(MIMEType *   const MIMETypeP,
+                      const char * const fileName);
+
+const char *
+MIMETypeFromFileName(const char * const fileName);
+
+const char *
+MIMETypeGuessFromFile2(MIMEType *   const MIMETypeP,
+                       const char * const fileName);
+
+const char *
+MIMETypeGuessFromFile(const char * const filename);
+
+
+/****************************************************************************
+  STUFF THAT PROBABLY DOESN'T BELONG IN THIS FILE BECAUSE IT IS INTERNAL
+
+  Some day, we sort this out.
+****************************************************************************/
+
+
+#define CR      '\r'
+#define LF      '\n'
+#define CRLF    "\r\n"
+
+/*********************************************************************
+** Paths and so on...
+*********************************************************************/
+
+#ifdef WIN32
+#define DEFAULT_ROOT        "c:\\abyss"
+#define DEFAULT_DOCS        DEFAULT_ROOT"\\htdocs"
+#define DEFAULT_CONF_FILE   DEFAULT_ROOT"\\conf\\abyss.conf"
+#define DEFAULT_LOG_FILE    DEFAULT_ROOT"\\log\\abyss.log"
+#else
+#ifdef __rtems__
+#define DEFAULT_ROOT        "/abyss"
+#else
+#define DEFAULT_ROOT        "/usr/local/abyss"
+#endif
+#define DEFAULT_DOCS        DEFAULT_ROOT"/htdocs"
+#define DEFAULT_CONF_FILE   DEFAULT_ROOT"/conf/abyss.conf"
+#define DEFAULT_LOG_FILE    DEFAULT_ROOT"/log/abyss.log"
+#endif
+
+/*********************************************************************
+** Maximum number of simultaneous connections
+*********************************************************************/
+
+#define MAX_CONN    16
+
+/*********************************************************************
+** General purpose definitions
+*********************************************************************/
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif  /* NULL */
+
+#ifndef TRUE
+#define TRUE    1
+#endif  /* TRUE */
+
+#ifndef FALSE
+#define FALSE    0
+#endif  /* FALSE */
+
+/*********************************************************************
+** Buffer
+*********************************************************************/
+
+typedef struct
+{
+    void *data;
+    uint32_t size;
+    uint32_t staticid;
+} TBuffer;
+
+abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize);
+abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize);
+void BufferFree(TBuffer *buf);
+
+
+/*********************************************************************
+** String
+*********************************************************************/
+
+typedef struct
+{
+    TBuffer buffer;
+    uint32_t size;
+} TString;
+
+abyss_bool StringAlloc(TString *s);
+abyss_bool StringConcat(TString *s,char *s2);
+abyss_bool StringBlockConcat(TString *s,char *s2,char **ref);
+void StringFree(TString *s);
+char *StringData(TString *s);
+
+
+/*********************************************************************
+** Range
+*********************************************************************/
+
+abyss_bool
+RangeDecode(char *str,
+            uint64_t filesize,
+            uint64_t *start,
+            uint64_t *end);
+
+abyss_bool DateInit(void);
+
+/*********************************************************************
+** Base64
+*********************************************************************/
+
+void Base64Encode(char *s,char *d);
+
+/*********************************************************************
+** Session
+*********************************************************************/
+
+abyss_bool SessionLog(TSession *s);
+
+
+#ifdef __cplusplus
+}
+
+
+#endif
+
+/*****************************************************************************
+** Here is the copyright notice from the Abyss web server project file from
+** which this file is derived.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
+#endif  /* _ABYSS_H_ */
diff --git a/include/xmlrpc-c/base.h b/include/xmlrpc-c/base.h
new file mode 100644 (file)
index 0000000..45f18ef
--- /dev/null
@@ -0,0 +1,616 @@
+/* Copyright and license information is at the end of the file */
+
+#ifndef XMLRPC_H_INCLUDED
+#define XMLRPC_H_INCLUDED
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <time.h>
+#include <xmlrpc-c/util.h>
+#include <xmlrpc-c/config.h>  /* Defines XMLRPC_HAVE_WCHAR */
+
+#if XMLRPC_HAVE_WCHAR
+#include <wchar.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*=========================================================================
+**  Typedefs
+**=========================================================================
+**  We define names for these types, because they may change from platform
+**  to platform.
+*/
+
+typedef signed int xmlrpc_int;  
+    /* An integer of the type defined by XML-RPC <int>; i.e. 32 bit */
+typedef signed int xmlrpc_int32;
+    /* An integer of the type defined by XML-RPC <int4>; i.e. 32 bit */
+typedef int xmlrpc_bool;
+    /* A boolean (of the type defined by XML-RPC <boolean>, but there's
+       really only one kind)
+    */
+typedef double xmlrpc_double;
+    /* A double precision floating point number as defined by
+       XML-RPC <float>.  But the C "double" type is universally the same,
+       so it's probably clearer just to use that.  This typedef is here 
+       for mathematical completeness.
+    */
+
+#ifdef _WIN32
+typedef SOCKET xmlrpc_socket;
+#else
+typedef int xmlrpc_socket;
+#endif
+
+#define XMLRPC_INT32_MAX (2147483647)
+#define XMLRPC_INT32_MIN (-XMLRPC_INT32_MAX - 1)
+
+
+
+/*=========================================================================
+**  xmlrpc_value
+**=========================================================================
+**  An XML-RPC value (of any type).
+*/
+
+typedef enum {
+    XMLRPC_TYPE_INT      = 0,
+    XMLRPC_TYPE_BOOL     = 1,
+    XMLRPC_TYPE_DOUBLE   = 2,
+    XMLRPC_TYPE_DATETIME = 3,
+    XMLRPC_TYPE_STRING   = 4,
+    XMLRPC_TYPE_BASE64   = 5,
+    XMLRPC_TYPE_ARRAY    = 6,
+    XMLRPC_TYPE_STRUCT   = 7,
+    XMLRPC_TYPE_C_PTR    = 8,
+    XMLRPC_TYPE_NIL      = 9,
+    XMLRPC_TYPE_DEAD     = 0xDEAD
+} xmlrpc_type;
+
+/* These are *always* allocated on the heap. No exceptions. */
+typedef struct _xmlrpc_value xmlrpc_value;
+
+void
+xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP);
+
+#define XMLRPC_ASSERT_ARRAY_OK(val) \
+    xmlrpc_abort_if_array_bad(val)
+
+/* Increment the reference count of an xmlrpc_value. */
+extern void xmlrpc_INCREF (xmlrpc_value* value);
+
+/* Decrement the reference count of an xmlrpc_value. If there
+** are no more references, free it. */
+extern void xmlrpc_DECREF (xmlrpc_value* value);
+
+/* Get the type of an XML-RPC value. */
+extern xmlrpc_type xmlrpc_value_type (xmlrpc_value* value);
+
+xmlrpc_value *
+xmlrpc_int_new(xmlrpc_env * const envP,
+               int          const intValue);
+
+void 
+xmlrpc_read_int(xmlrpc_env *         const envP,
+                const xmlrpc_value * const valueP,
+                int *                const intValueP);
+
+xmlrpc_value *
+xmlrpc_bool_new(xmlrpc_env * const envP,
+                xmlrpc_bool  const boolValue);
+
+void
+xmlrpc_read_bool(xmlrpc_env *         const envP,
+                 const xmlrpc_value * const valueP,
+                 xmlrpc_bool *        const boolValueP);
+
+xmlrpc_value *
+xmlrpc_double_new(xmlrpc_env * const envP,
+                  double       const doubleValue);
+
+void
+xmlrpc_read_double(xmlrpc_env *         const envP,
+                   const xmlrpc_value * const valueP,
+                   xmlrpc_double *      const doubleValueP);
+
+xmlrpc_value *
+xmlrpc_datetime_new_str(xmlrpc_env * const envP,
+                        const char * const value);
+
+xmlrpc_value *
+xmlrpc_datetime_new_sec(xmlrpc_env * const envP, 
+                        time_t       const value);
+
+void
+xmlrpc_read_datetime_str(xmlrpc_env *         const envP,
+                         const xmlrpc_value * const valueP,
+                         const char **        const stringValueP);
+
+void
+xmlrpc_read_datetime_sec(xmlrpc_env *         const envP,
+                         const xmlrpc_value * const valueP,
+                         time_t *             const timeValueP);
+
+xmlrpc_value *
+xmlrpc_string_new(xmlrpc_env * const envP,
+                  const char * const stringValue);
+
+xmlrpc_value *
+xmlrpc_string_new_lp(xmlrpc_env * const envP, 
+                     size_t       const length,
+                     const char * const stringValue);
+
+void
+xmlrpc_read_string(xmlrpc_env *         const envP,
+                   const xmlrpc_value * const valueP,
+                   const char **        const stringValueP);
+
+
+void
+xmlrpc_read_string_lp(xmlrpc_env *         const envP,
+                      const xmlrpc_value * const valueP,
+                      size_t *             const lengthP,
+                      const char **        const stringValueP);
+
+#if XMLRPC_HAVE_WCHAR
+xmlrpc_value *
+xmlrpc_string_w_new(xmlrpc_env *    const envP,
+                    const wchar_t * const stringValue);
+
+xmlrpc_value *
+xmlrpc_string_w_new_lp(xmlrpc_env *    const envP, 
+                       size_t          const length,
+                       const wchar_t * const stringValue);
+
+void
+xmlrpc_read_string_w(xmlrpc_env *     const envP,
+                     xmlrpc_value *   const valueP,
+                     const wchar_t ** const stringValueP);
+
+void
+xmlrpc_read_string_w_lp(xmlrpc_env *     const envP,
+                        xmlrpc_value *   const valueP,
+                        size_t *         const lengthP,
+                        const wchar_t ** const stringValueP);
+
+#endif /* XMLRPC_HAVE_WCHAR */
+
+xmlrpc_value *
+xmlrpc_base64_new(xmlrpc_env *          const envP, 
+                  size_t                const length,
+                  const unsigned char * const value);
+
+void
+xmlrpc_read_base64(xmlrpc_env *           const envP,
+                   const xmlrpc_value *   const valueP,
+                   size_t *               const lengthP,
+                   const unsigned char ** const bytestringValueP);
+
+void
+xmlrpc_read_base64_size(xmlrpc_env *           const envP,
+                        const xmlrpc_value *   const valueP,
+                        size_t *               const lengthP);
+
+xmlrpc_value *
+xmlrpc_array_new(xmlrpc_env * const envP);
+
+/* Return the number of elements in an XML-RPC array.
+** Sets XMLRPC_TYPE_ERROR if 'array' is not an array. */
+int 
+xmlrpc_array_size(xmlrpc_env *         const env, 
+                  const xmlrpc_value * const array);
+
+/* Append an item to an XML-RPC array.
+** Sets XMLRPC_TYPE_ERROR if 'array' is not an array. */
+extern void
+xmlrpc_array_append_item (xmlrpc_env   * envP,
+                          xmlrpc_value * arrayP,
+                          xmlrpc_value * valueP);
+
+void
+xmlrpc_array_read_item(xmlrpc_env *         const envP,
+                       const xmlrpc_value * const arrayP,
+                       unsigned int         const index,
+                       xmlrpc_value **      const valuePP);
+
+/* Deprecated.  Use xmlrpc_array_read_item() instead.
+
+   Get an item from an XML-RPC array.
+   Does not increment the reference count of the returned value.
+   Sets XMLRPC_TYPE_ERROR if 'array' is not an array.
+   Sets XMLRPC_INDEX_ERROR if 'index' is out of bounds.
+*/
+xmlrpc_value * 
+xmlrpc_array_get_item(xmlrpc_env *         const envP,
+                      const xmlrpc_value * const arrayP,
+                      int                  const index);
+
+/* Not implemented--we don't need it yet.
+extern 
+int xmlrpc_array_set_item (xmlrpc_env* env,
+xmlrpc_value* array,
+int index,
+                                  xmlrpc_value* value);
+*/
+
+void
+xmlrpc_read_nil(xmlrpc_env *   const envP,
+                xmlrpc_value * const valueP);
+                
+
+void
+xmlrpc_read_cptr(xmlrpc_env *         const envP,
+                 const xmlrpc_value * const valueP,
+                 void **              const ptrValueP);
+
+xmlrpc_value *
+xmlrpc_struct_new(xmlrpc_env * env);
+
+/* Return the number of key/value pairs in a struct.
+** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */
+int
+xmlrpc_struct_size (xmlrpc_env   * env, 
+                    xmlrpc_value * strct);
+
+/* Returns true iff 'strct' contains 'key'.
+** Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. */
+int 
+xmlrpc_struct_has_key(xmlrpc_env *   const envP,
+                      xmlrpc_value * const strctP,
+                      const char *   const key);
+
+/* The same as the above, but the key may contain zero bytes.
+   Deprecated.  xmlrpc_struct_get_value_v() is more general, and this
+   case is not common enough to warrant a shortcut.
+*/
+int 
+xmlrpc_struct_has_key_n(xmlrpc_env   * const envP,
+                        xmlrpc_value * const strctP,
+                        const char *   const key, 
+                        size_t         const key_len);
+
+#if 0
+/* Not implemented yet, but needed for completeness. */
+int
+xmlrpc_struct_has_key_v(xmlrpc_env *   env, 
+                        xmlrpc_value * strct,
+                        xmlrpc_value * const keyval);
+#endif
+
+
+void
+xmlrpc_struct_find_value(xmlrpc_env *    const envP,
+                         xmlrpc_value *  const structP,
+                         const char *    const key,
+                         xmlrpc_value ** const valuePP);
+
+
+void
+xmlrpc_struct_find_value_v(xmlrpc_env *    const envP,
+                           xmlrpc_value *  const structP,
+                           xmlrpc_value *  const keyP,
+                           xmlrpc_value ** const valuePP);
+
+void
+xmlrpc_struct_read_value_v(xmlrpc_env *    const envP,
+                           xmlrpc_value *  const structP,
+                           xmlrpc_value *  const keyP,
+                           xmlrpc_value ** const valuePP);
+
+void
+xmlrpc_struct_read_value(xmlrpc_env *    const envP,
+                         xmlrpc_value *  const strctP,
+                         const char *    const key,
+                         xmlrpc_value ** const valuePP);
+
+/* The "get_value" functions are deprecated.  Use the "find_value"
+   and "read_value" functions instead.
+*/
+xmlrpc_value * 
+xmlrpc_struct_get_value(xmlrpc_env *   const envP,
+                        xmlrpc_value * const strctP,
+                        const char *   const key);
+
+/* The same as above, but the key may contain zero bytes. 
+   Deprecated.  xmlrpc_struct_get_value_v() is more general, and this
+   case is not common enough to warrant a shortcut.
+*/
+xmlrpc_value * 
+xmlrpc_struct_get_value_n(xmlrpc_env *   const envP,
+                          xmlrpc_value * const strctP,
+                          const char *   const key, 
+                          size_t         const key_len);
+
+/* Set the value associated with 'key' in 'strct' to 'value'.
+   Sets XMLRPC_TYPE_ERROR if 'strct' is not a struct. 
+*/
+void 
+xmlrpc_struct_set_value(xmlrpc_env *   const env,
+                        xmlrpc_value * const strct,
+                        const char *   const key,
+                        xmlrpc_value * const value);
+
+/* The same as above, but the key may contain zero bytes.  Deprecated.
+   The general way to set a structure value is xmlrpc_struct_set_value_v(),
+   and this case is not common enough to deserve a shortcut.
+*/
+void 
+xmlrpc_struct_set_value_n(xmlrpc_env *    const env,
+                          xmlrpc_value *  const strct,
+                          const char *    const key, 
+                          size_t          const key_len,
+                          xmlrpc_value *  const value);
+
+/* The same as above, but the key must be an XML-RPC string.
+** Fails with XMLRPC_TYPE_ERROR if 'keyval' is not a string. */
+void 
+xmlrpc_struct_set_value_v(xmlrpc_env *   const env,
+                          xmlrpc_value * const strct,
+                          xmlrpc_value * const keyval,
+                          xmlrpc_value * const value);
+
+/* Given a zero-based index, return the matching key and value. This
+** is normally used in conjunction with xmlrpc_struct_size.
+** Fails with XMLRPC_TYPE_ERROR if 'struct' is not a struct.
+** Fails with XMLRPC_INDEX_ERROR if 'index' is out of bounds. */
+
+void 
+xmlrpc_struct_read_member(xmlrpc_env *    const envP,
+                          xmlrpc_value *  const structP,
+                          unsigned int    const index,
+                          xmlrpc_value ** const keyvalP,
+                          xmlrpc_value ** const valueP);
+
+/* The same as above, but does not increment the reference count of the
+   two values it returns, and return NULL for both if it fails, and
+   takes a signed integer for the index (but fails if it is negative).
+
+   Deprecated.  Use xmlrpc_struct_read_member() instead.
+*/
+void
+xmlrpc_struct_get_key_and_value(xmlrpc_env *    env,
+                                xmlrpc_value *  strct,
+                                int             index,
+                                xmlrpc_value ** out_keyval,
+                                xmlrpc_value ** out_value);
+
+xmlrpc_value *
+xmlrpc_cptr_new(xmlrpc_env * const envP,
+                void *       const value);
+
+xmlrpc_value *
+xmlrpc_nil_new(xmlrpc_env * const envP);
+
+
+/* Build an xmlrpc_value from a format string. */
+
+xmlrpc_value * 
+xmlrpc_build_value(xmlrpc_env * const env,
+                   const char * const format, 
+                   ...);
+
+/* The same as the above, but using a va_list and more general */
+void
+xmlrpc_build_value_va(xmlrpc_env *    const env,
+                      const char *    const format,
+                      va_list               args,
+                      xmlrpc_value ** const valPP,
+                      const char **   const tailP);
+
+void 
+xmlrpc_decompose_value(xmlrpc_env *   const envP,
+                       xmlrpc_value * const value,
+                       const char *   const format, 
+                       ...);
+
+void 
+xmlrpc_decompose_value_va(xmlrpc_env *   const envP,
+                          xmlrpc_value * const value,
+                          const char *   const format,
+                          va_list              args);
+
+/* xmlrpc_parse_value... is the same as xmlrpc_decompose_value... except
+   that it doesn't do proper memory management -- it returns xmlrpc_value's
+   without incrementing the reference count and returns pointers to data
+   inside an xmlrpc_value structure.
+
+   These are deprecated.  Use xmlrpc_decompose_value... instead.
+*/
+void 
+xmlrpc_parse_value(xmlrpc_env *   const envP,
+                   xmlrpc_value * const value,
+                   const char *   const format, 
+                   ...);
+
+/* The same as the above, but using a va_list. */
+void 
+xmlrpc_parse_value_va(xmlrpc_env *   const envP,
+                      xmlrpc_value * const value,
+                      const char *   const format,
+                      va_list              args);
+
+/*=========================================================================
+**  Encoding XML
+**=======================================================================*/
+
+/* Serialize an XML value without any XML header. This is primarily used
+** for testing purposes. */
+void
+xmlrpc_serialize_value(xmlrpc_env *       env,
+                       xmlrpc_mem_block * output,
+                       xmlrpc_value *     value);
+
+/* Serialize a list of parameters without any XML header. This is
+** primarily used for testing purposes. */
+void
+xmlrpc_serialize_params(xmlrpc_env *       env,
+                        xmlrpc_mem_block * output,
+                        xmlrpc_value *     param_array);
+
+/* Serialize an XML-RPC call. */
+void 
+xmlrpc_serialize_call (xmlrpc_env *       const env,
+                       xmlrpc_mem_block * const output,
+                       const char *       const method_name,
+                       xmlrpc_value *     const param_array);
+
+/* Serialize an XML-RPC return value. */
+extern void
+xmlrpc_serialize_response(xmlrpc_env *       env,
+                          xmlrpc_mem_block * output,
+                          xmlrpc_value *     value);
+
+/* Serialize an XML-RPC fault (as specified by 'fault'). */
+extern void
+xmlrpc_serialize_fault(xmlrpc_env *       env,
+                       xmlrpc_mem_block * output,
+                       xmlrpc_env *       fault);
+
+
+/*=========================================================================
+**  Decoding XML
+**=======================================================================*/
+
+/* Parse an XML-RPC call. If an error occurs, set a fault and set
+** the output variables to NULL.
+** The caller is responsible for calling free(*out_method_name) and
+** xmlrpc_DECREF(*out_param_array). */
+void 
+xmlrpc_parse_call(xmlrpc_env *    const envP,
+                  const char *    const xml_data,
+                  size_t          const xml_len,
+                  const char **   const out_method_name,
+                  xmlrpc_value ** const out_param_array);
+
+void
+xmlrpc_parse_response2(xmlrpc_env *    const envP,
+                       const char *    const xmlData,
+                       size_t          const xmlDataLen,
+                       xmlrpc_value ** const resultPP,
+                       int *           const faultCodeP,
+                       const char **   const faultStringP);
+
+
+/* xmlrpc_parse_response() is for backward compatibility */
+
+xmlrpc_value *
+xmlrpc_parse_response(xmlrpc_env * const envP, 
+                      const char * const xmlData, 
+                      size_t       const xmlDataLen);
+
+
+/*=========================================================================
+**  XML-RPC Base64 Utilities
+**=========================================================================
+**  Here are some lightweight utilities which can be used to encode and
+**  decode Base64 data. These are exported mainly for testing purposes.
+*/
+
+/* This routine inserts newlines every 76 characters, as required by the
+** Base64 specification. */
+xmlrpc_mem_block *
+xmlrpc_base64_encode(xmlrpc_env *    env,
+                     unsigned char * bin_data,
+                     size_t          bin_len);
+
+/* This routine encodes everything in one line. This is needed for HTTP
+** authentication and similar tasks. */
+xmlrpc_mem_block *
+xmlrpc_base64_encode_without_newlines(xmlrpc_env *    env,
+                                      unsigned char * bin_data,
+                                      size_t          bin_len);
+
+/* This decodes Base64 data with or without newlines. */
+extern xmlrpc_mem_block *
+xmlrpc_base64_decode(xmlrpc_env * const envP,
+                     const char * const ascii_data,
+                     size_t       const ascii_len);
+
+
+/*=========================================================================
+**  UTF-8 Encoding and Decoding
+**=========================================================================
+**  We need a correct, reliable and secure UTF-8 decoder. This decoder
+**  raises a fault if it encounters invalid UTF-8.
+**
+**  Note that ANSI C does not precisely define the representation used
+**  by wchar_t--it may be UCS-2, UTF-16, UCS-4, or something from outer
+**  space. If your platform does something especially bizarre, you may
+**  need to reimplement these routines.
+*/
+
+/* Ensure that a string contains valid, legally-encoded UTF-8 data.
+   (Incorrectly-encoded UTF-8 strings are often used to bypass security
+   checks.)
+*/
+void 
+xmlrpc_validate_utf8 (xmlrpc_env * const env,
+                      const char * const utf8_data,
+                      size_t       const utf8_len);
+
+/* Decode a UTF-8 string. */
+xmlrpc_mem_block *
+xmlrpc_utf8_to_wcs(xmlrpc_env * const envP,
+                   const char * const utf8_data,
+                   size_t       const utf8_len);
+
+/* Encode a UTF-8 string. */
+
+#if XMLRPC_HAVE_WCHAR
+xmlrpc_mem_block *
+xmlrpc_wcs_to_utf8(xmlrpc_env * env,
+                   wchar_t *    wcs_data,
+                   size_t       wcs_len);
+#endif
+
+/*=========================================================================
+**  Authorization Cookie Handling
+**=========================================================================
+**  Routines to get and set values for authorizing via authorization
+**  cookies. Both the client and server use HTTP_COOKIE_AUTH to store
+**  the representation of the authorization value, which is actually
+**  just a base64 hash of username:password. (This entire method is
+**  a cookie replacement of basic authentication.)
+**/
+
+extern void xmlrpc_authcookie_set(xmlrpc_env * env,
+                                  const char * username,
+                                  const char * password);
+
+char *xmlrpc_authcookie(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#endif
+
diff --git a/include/xmlrpc-c/base.hpp b/include/xmlrpc-c/base.hpp
new file mode 100644 (file)
index 0000000..c3dac8b
--- /dev/null
@@ -0,0 +1,312 @@
+#ifndef XMLRPC_BASE_HPP_INCLUDED
+#define XMLRPC_BASE_HPP_INCLUDED
+
+#include <climits>
+#include <cfloat>
+#include <ctime>
+#include <vector>
+#include <map>
+#include <string>
+
+#include <xmlrpc-c/base.h>
+
+namespace xmlrpc_c {
+
+
+class value {
+    // This is a handle.  You don't want to create a pointer to this;
+    // it is in fact a pointer itself.
+public:
+    value();
+        // This creates a placeholder.  It can't be used for anything, but
+        // holds memory.  instantiate() can turn it into a real object.
+
+    value(xmlrpc_c::value const &value);  // copy constructor
+
+    ~value();
+
+    enum type_t {
+        TYPE_INT        = 0,
+        TYPE_BOOLEAN    = 1,
+        TYPE_DOUBLE     = 2,
+        TYPE_DATETIME   = 3,
+        TYPE_STRING     = 4,
+        TYPE_BYTESTRING = 5,
+        TYPE_ARRAY      = 6,
+        TYPE_STRUCT     = 7,
+        TYPE_C_PTR      = 8,
+        TYPE_NIL        = 9,
+        TYPE_DEAD       = 0xDEAD
+    };
+
+    type_t type() const;
+
+    xmlrpc_c::value&
+    operator=(xmlrpc_c::value const&);
+
+    // The following are not meant to be public to users, but just to
+    // other Xmlrpc-c library modules.  If we ever go to a pure C++
+    // implementation, not based on C xmlrpc_value objects, this shouldn't
+    // be necessary.
+
+    void
+    appendToCArray(xmlrpc_value * const arrayP) const;
+
+    void
+    addToCStruct(xmlrpc_value * const structP,
+                    std::string const key) const;
+
+    xmlrpc_value *
+    cValue() const;
+
+    value(xmlrpc_value * const valueP);
+
+    void
+    instantiate(xmlrpc_value * const valueP);
+        // Work only on a placeholder object created by the no-argument
+        // constructor.
+
+    xmlrpc_value * cValueP;
+        // NULL means this is merely a placeholder object.
+};
+
+
+
+class value_int : public value {
+public:
+    value_int(int const cvalue);
+
+    value_int(xmlrpc_c::value const baseValue);
+
+    operator int() const;
+};
+
+
+
+class value_boolean : public value {
+public:
+    value_boolean(bool const cvalue);
+
+    value_boolean(xmlrpc_c::value const baseValue);
+
+    operator bool() const;
+};
+
+
+
+class value_string : public value {
+public:
+    value_string(std::string const& cvalue);
+
+    value_string(xmlrpc_c::value const baseValue);
+
+    operator std::string() const;
+};
+
+
+
+class value_double : public value {
+public:
+    value_double(double const cvalue);
+
+    value_double(xmlrpc_c::value const baseValue);
+
+    operator double() const;
+};
+
+
+
+class value_datetime : public value {
+public:
+    value_datetime(std::string const cvalue);
+    value_datetime(time_t const cvalue);
+    value_datetime(struct timeval const& cvalue);
+    value_datetime(struct timespec const& cvalue);
+
+    value_datetime(xmlrpc_c::value const baseValue);
+
+    operator time_t() const;
+};
+
+
+
+class value_bytestring : public value {
+public:
+    value_bytestring(std::vector<unsigned char> const& cvalue);
+
+    value_bytestring(xmlrpc_c::value const baseValue);
+
+    // You can't cast to a vector because the compiler can't tell which
+    // constructor to use (complains about ambiguity).  So we have this:
+    std::vector<unsigned char>
+    vectorUcharValue() const;
+
+    size_t
+    length() const;
+};
+
+
+
+class value_nil : public value {
+public:
+    value_nil();
+
+    value_nil(xmlrpc_c::value const baseValue);
+};
+
+
+
+class value_struct : public value {
+public:
+    value_struct(std::map<std::string, xmlrpc_c::value> const& cvalue);
+
+    value_struct(xmlrpc_c::value const baseValue);
+
+    operator std::map<std::string, xmlrpc_c::value>() const;
+};
+
+
+
+class value_array : public value {
+public:
+    value_array(std::vector<xmlrpc_c::value> const& cvalue);
+
+    value_array(xmlrpc_c::value const baseValue);
+
+    std::vector<xmlrpc_c::value>
+    vectorValueValue() const;
+
+    size_t
+    size() const;
+};
+
+
+
+class fault {
+/*----------------------------------------------------------------------------
+   This is an XML-RPC fault.
+
+   This object is not intended to be used to represent a fault in the
+   execution of XML-RPC client/server software -- just a fault in an
+   XML-RPC RPC as described by the XML-RPC spec.
+
+   There is no way to represent "no fault" with this object.  The object is
+   meaningful only in the context of some fault.
+-----------------------------------------------------------------------------*/
+public:
+    enum code_t {
+        CODE_UNSPECIFIED            =    0,
+        CODE_INTERNAL               = -500,
+        CODE_TYPE                   = -501,
+        CODE_INDEX                  = -502,
+        CODE_PARSE                  = -503,
+        CODE_NETWORK                = -504,
+        CODE_TIMEOUT                = -505,
+        CODE_NO_SUCH_METHOD         = -506,
+        CODE_REQUEST_REFUSED        = -507,
+        CODE_INTROSPECTION_DISABLED = -508,
+        CODE_LIMIT_EXCEEDED         = -509,
+        CODE_INVALID_UTF8           = -510
+    };
+
+    fault();
+
+    fault(std::string             const _faultString,
+          xmlrpc_c::fault::code_t const _faultCode 
+              = xmlrpc_c::fault::CODE_UNSPECIFIED
+        );
+    
+    xmlrpc_c::fault::code_t getCode() const;
+
+    std::string getDescription() const;
+
+private:
+    bool                    valid;
+    xmlrpc_c::fault::code_t code;
+    std::string             description;
+};
+
+class rpcOutcome {
+/*----------------------------------------------------------------------------
+  The outcome of a validly executed RPC -- either an XML-RPC fault
+  or an XML-RPC value of the result.
+-----------------------------------------------------------------------------*/
+public:
+    rpcOutcome();
+    rpcOutcome(xmlrpc_c::value const result);
+    rpcOutcome(xmlrpc_c::fault const fault);
+    bool succeeded() const;
+    xmlrpc_c::fault getFault() const;
+    xmlrpc_c::value getResult() const;
+private:
+    bool valid;
+        // This is false in a placeholder variable -- i.e. an object you
+        // create with the no-argument constructor, which is waiting to be
+        // assigned a value.  When false, nothing below is valid.
+    bool _succeeded;
+    xmlrpc_c::value result;  // valid if 'succeeded'
+    xmlrpc_c::fault fault;   // valid if not 'succeeded'
+};
+
+class paramList {
+/*----------------------------------------------------------------------------
+   A parameter list of an XML-RPC call.
+-----------------------------------------------------------------------------*/
+public:
+    paramList(unsigned int const paramCount = 0);
+
+    void
+    add(xmlrpc_c::value const param);
+
+    unsigned int
+    size() const;
+
+    xmlrpc_c::value operator[](unsigned int const subscript) const;
+
+    int
+    getInt(unsigned int const paramNumber,
+           int          const minimum = INT_MIN,
+           int          const maximum = INT_MAX) const;
+
+    bool
+    getBoolean(unsigned int const paramNumber) const;
+
+    double
+    getDouble(unsigned int const paramNumber,
+              double       const minimum = -DBL_MAX,
+              double       const maximum = DBL_MAX) const;
+
+    enum timeConstraint {TC_ANY, TC_NO_PAST, TC_NO_FUTURE};
+
+    time_t
+    getDatetime_sec(unsigned int   const paramNumber,
+                    timeConstraint const constraint
+                        = paramList::TC_ANY) const;
+
+    std::string
+    getString(unsigned int const paramNumber) const;
+
+    std::vector<unsigned char>
+    getBytestring(unsigned int const paramNumber) const;
+
+    std::vector<xmlrpc_c::value>
+    getArray(unsigned int const paramNumber,
+             unsigned int const minSize = 0,
+             unsigned int const maxSize = UINT_MAX) const;
+
+    std::map<std::string, xmlrpc_c::value>
+    getStruct(unsigned int const paramNumber) const;
+
+    void
+    getNil(unsigned int const paramNumber) const;
+
+    void
+    verifyEnd(unsigned int const paramNumber) const;
+
+private:
+    std::vector<xmlrpc_c::value> paramVector;
+};
+
+} // namespace
+
+#endif
diff --git a/include/xmlrpc-c/base64.hpp b/include/xmlrpc-c/base64.hpp
new file mode 100644 (file)
index 0000000..a884225
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef XMLRPC_BASE64_HPP_INCLUDED
+#define XMLRPC_BASE64_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+
+namespace xmlrpc_c {
+
+
+enum newlineCtl {NEWLINE_NO, NEWLINE_YES};
+
+std::string
+base64FromBytes(
+    std::vector<unsigned char> const& bytes,
+    xmlrpc_c::newlineCtl       const  newlineCtl = xmlrpc_c::NEWLINE_YES);
+
+
+
+std::vector<unsigned char>
+bytesFromBase64(std::string const& base64);
+
+
+} // namespace
+
+#endif
diff --git a/include/xmlrpc-c/base_int.h b/include/xmlrpc-c/base_int.h
new file mode 100644 (file)
index 0000000..cd5ef3e
--- /dev/null
@@ -0,0 +1,176 @@
+/*============================================================================
+                         base_int.h
+==============================================================================
+  This header file defines the interface between modules inside
+  xmlrpc-c.
+
+  Use this in addition to xmlrpc.h, which defines the external
+  interface.
+
+  Copyright information is at the end of the file.
+============================================================================*/
+
+
+#ifndef  XMLRPC_C_BASE_INT_H_INCLUDED
+#define  XMLRPC_C_BASE_INT_H_INCLUDED
+
+#include "xmlrpc_config.h"
+#include "bool.h"
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/util_int.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct _xmlrpc_value {
+    xmlrpc_type _type;
+    int _refcount;
+
+    /* Certain data types store their data directly in the xmlrpc_value. */
+    union {
+        xmlrpc_int32 i;
+        xmlrpc_bool b;
+        double d;
+        /* time_t t */
+        void *c_ptr;
+    } _value;
+    
+    /* Other data types use a memory block.
+
+       For a string, this is the characters of the string in UTF-8, plus
+       a NUL added to the end.
+    */
+    xmlrpc_mem_block _block;
+
+    xmlrpc_mem_block *_wcs_block;
+        /* This is a copy of the string value in _block, but in UTF-16
+           instead of UTF-8.  This member is not always present.  If NULL,
+           it is not present.
+
+           We keep this copy for convenience.  The value is totally
+           redundant with _block.
+
+           This member is always NULL when the data type is not string.
+
+           This member is always NULL on a system that does not have
+           Unicode wchar functions.
+        */
+};
+
+#define XMLRPC_ASSERT_VALUE_OK(val) \
+    XMLRPC_ASSERT((val) != NULL && (val)->_type != XMLRPC_TYPE_DEAD)
+
+/* A handy type-checking routine. */
+#define XMLRPC_TYPE_CHECK(env,v,t) \
+    do \
+        if ((v)->_type != (t)) \
+            XMLRPC_FAIL(env, XMLRPC_TYPE_ERROR, "Expected " #t); \
+    while (0)
+
+
+typedef struct {
+    unsigned char key_hash;
+    xmlrpc_value *key;
+    xmlrpc_value *value;
+} _struct_member;
+
+
+void
+xmlrpc_createXmlrpcValue(xmlrpc_env *    const envP,
+                         xmlrpc_value ** const valPP);
+
+const char *
+xmlrpc_typeName(xmlrpc_type const type);
+
+void
+xmlrpc_traceXml(const char * const label, 
+                const char * const xml,
+                unsigned int const xmlLength);
+
+void
+xmlrpc_destroyStruct(xmlrpc_value * const structP);
+
+void
+xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP);
+
+/*----------------------------------------------------------------------------
+   The following are for use by the legacy xmlrpc_parse_value().  They don't
+   do proper memory management, so they aren't appropriate for general use,
+   but there are old users that do xmlrpc_parse_value() and compensate for
+   the memory management, so we have to continue to offer this style of
+   memory management.
+
+   In particular, the functions that return xmlrpc_values don't increment
+   the reference count, and the functions that return strings don't allocate
+   new memory for them.
+-----------------------------------------------------------------------------*/
+
+void
+xmlrpc_read_datetime_str_old(xmlrpc_env *         const envP,
+                             const xmlrpc_value * const valueP,
+                             const char **        const stringValueP);
+
+void
+xmlrpc_read_string_old(xmlrpc_env *         const envP,
+                       const xmlrpc_value * const valueP,
+                       const char **        const stringValueP);
+
+void
+xmlrpc_read_string_lp_old(xmlrpc_env *         const envP,
+                          const xmlrpc_value * const valueP,
+                          size_t *             const lengthP,
+                          const char **        const stringValueP);
+
+#if XMLRPC_HAVE_WCHAR
+void
+xmlrpc_read_string_w_old(xmlrpc_env *     const envP,
+                         xmlrpc_value *   const valueP,
+                         const wchar_t ** const stringValueP);
+
+void
+xmlrpc_read_string_w_lp_old(xmlrpc_env *     const envP,
+                            xmlrpc_value *   const valueP,
+                            size_t *         const lengthP,
+                            const wchar_t ** const stringValueP);
+#endif
+
+void
+xmlrpc_read_base64_old(xmlrpc_env *           const envP,
+                       const xmlrpc_value *   const valueP,
+                       size_t *               const lengthP,
+                       const unsigned char ** const byteStringValueP);
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/xmlrpc-c/client.h b/include/xmlrpc-c/client.h
new file mode 100644 (file)
index 0000000..6e08ea1
--- /dev/null
@@ -0,0 +1,246 @@
+/*============================================================================
+                         xmlrpc_client.h
+==============================================================================
+  This header file defines the interface between xmlrpc.c and its users,
+  related to clients.
+
+  Copyright information is at the end of the file.
+============================================================================*/
+
+#ifndef  XMLRPC_CLIENT_H_INCLUDED
+#define  XMLRPC_CLIENT_H_INCLUDED
+
+#include <xmlrpc-c/base.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct xmlrpc_client;
+#ifndef __cplusplus
+typedef struct xmlrpc_client xmlrpc_client;
+#endif
+
+struct xmlrpc_xportparms;
+    /* This is a "base class".  The struct is never complete; you're
+       supposed to cast between struct xmlrpc_xportparms * and 
+       "struct xmlrpc_..._xportparms *" in order to use it.  
+    */
+
+enum xmlrpc_sslversion {
+    XMLRPC_SSLVERSION_DEFAULT,
+    XMLRPC_SSLVERSION_TLSv1,
+    XMLRPC_SSLVERSION_SSLv2,
+    XMLRPC_SSLVERSION_SSLv3
+};
+
+struct xmlrpc_curl_xportparms {
+    /* This is designed so that zero values are always the defaults. */
+    const char * network_interface;
+    xmlrpc_bool  no_ssl_verifypeer;
+    xmlrpc_bool  no_ssl_verifyhost;
+    const char * user_agent;
+    const char * ssl_cert;
+    const char * sslcerttype;
+    const char * sslcertpasswd;
+    const char * sslkey;
+    const char * sslkeytype;
+    const char * sslkeypasswd;
+    const char * sslengine;
+    xmlrpc_bool  sslengine_default;
+    enum xmlrpc_sslversion sslversion;
+    const char * cainfo;
+    const char * capath;
+    const char * randomfile;
+    const char * egdsocket;
+    const char * ssl_cipher_list;
+};
+
+
+#define XMLRPC_CXPSIZE(mbrname) \
+    XMLRPC_STRUCTSIZE(struct xmlrpc_curl_xportparms, mbrname)
+
+/* XMLRPC_CXPSIZE(xyz) is analogous to XMLRPC_CPSIZE, below */
+
+struct xmlrpc_wininet_xportparms {
+    int allowInvalidSSLCerts;
+};
+
+#define XMLRPC_WXPSIZE(mbrname) \
+    XMLRPC_STRUCTSIZE(struct xmlrpc_wininet_xportparms, mbrname)
+
+/* XMLRPC_WXPSIZE(xyz) is analogous to XMLRPC_CPSIZE, below */
+
+struct xmlrpc_clientparms {
+    const char *               transport;
+    struct xmlrpc_xportparms * transportparmsP;
+        /* Cast a "struct ..._xportparms *" to fit here */
+    size_t                     transportparm_size;
+};
+
+#define XMLRPC_CPSIZE(mbrname) \
+  XMLRPC_STRUCTSIZE(struct xmlrpc_clientparms, mbrname)
+
+/* XMLRPC_CPSIZE(xyz) is the minimum size a struct xmlrpc_clientparms
+   must be to include the 'xyz' member.  This is essential to forward and
+   backward compatbility, as new members will be added to the end of the
+   struct in future releases.  This is how the callee knows whether or
+   not the caller is new enough to have supplied a certain parameter.
+*/
+
+const char * 
+xmlrpc_client_get_default_transport(xmlrpc_env * const env);
+
+/* A callback function to handle the response to an asynchronous call.
+** If 'fault->fault_occurred' is true, then response will be NULL. All
+** arguments except 'user_data' will be deallocated internally; please do
+** not free any of them yourself.
+** WARNING: param_array may (or may not) be NULL if fault->fault_occurred
+** is true, and you set up the call using xmlrpc_client_call_asynch.
+** WARNING: If asynchronous calls are still pending when the library is
+** shut down, your handler may (or may not) be called with a fault. */
+typedef void (*xmlrpc_response_handler) (const char *server_url,
+                                         const char *method_name,
+                                         xmlrpc_value *param_array,
+                                         void *user_data,
+                                         xmlrpc_env *fault,
+                                         xmlrpc_value *result);
+
+
+/*=========================================================================
+**  xmlrpc_server_info
+**=========================================================================
+**  We normally refer to servers by URL. But sometimes we need to do extra
+**  setup for particular servers. In that case, we can create an
+**  xmlrpc_server_info object, configure it in various ways, and call the
+**  remote server.
+**
+**  (This interface is also designed to discourage further multiplication
+**  of xmlrpc_client_call APIs. We have enough of those already. Please
+**  add future options and flags using xmlrpc_server_info.)
+*/
+
+typedef struct _xmlrpc_server_info xmlrpc_server_info;
+
+/* Create a new server info record, pointing to the specified server. */
+xmlrpc_server_info *
+xmlrpc_server_info_new(xmlrpc_env * const env,
+                       const char * const server_url);
+
+/* Create a new server info record, with a copy of the old server. */
+extern xmlrpc_server_info * 
+xmlrpc_server_info_copy(xmlrpc_env *env, xmlrpc_server_info *src_server);
+
+/* Delete a server info record. */
+extern void
+xmlrpc_server_info_free (xmlrpc_server_info *server);
+
+void 
+xmlrpc_server_info_set_basic_auth(xmlrpc_env *         const envP,
+                                  xmlrpc_server_info * const serverP,
+                                  const char *         const username,
+                                  const char *         const password);
+
+
+void
+xmlrpc_client_setup_global_const(xmlrpc_env * const envP);
+
+void
+xmlrpc_client_teardown_global_const(void);
+
+void 
+xmlrpc_client_create(xmlrpc_env *                      const envP,
+                     int                               const flags,
+                     const char *                      const appname,
+                     const char *                      const appversion,
+                     const struct xmlrpc_clientparms * const clientparmsP,
+                     unsigned int                      const parmSize,
+                     xmlrpc_client **                  const clientPP);
+
+void 
+xmlrpc_client_destroy(xmlrpc_client * const clientP);
+
+void
+xmlrpc_client_transport_call2(
+    xmlrpc_env *               const envP,
+    xmlrpc_client *            const clientP,
+    const xmlrpc_server_info * const serverP,
+    xmlrpc_mem_block *         const callXmlP,
+    xmlrpc_mem_block **        const respXmlPP);
+
+void
+xmlrpc_client_call2(xmlrpc_env *               const envP,
+                    struct xmlrpc_client *     const clientP,
+                    const xmlrpc_server_info * const serverInfoP,
+                    const char *               const methodName,
+                    xmlrpc_value *             const paramArrayP,
+                    xmlrpc_value **            const resultPP);
+
+void
+xmlrpc_client_call2f(xmlrpc_env *    const envP,
+                     xmlrpc_client * const clientP,
+                     const char *    const serverUrl,
+                     const char *    const methodName,
+                     xmlrpc_value ** const resultPP,
+                     const char *    const format,
+                     ...);
+
+void 
+xmlrpc_client_event_loop_finish(xmlrpc_client * const clientP);
+
+void 
+xmlrpc_client_event_loop_finish_timeout(xmlrpc_client * const clientP,
+                                        unsigned long   const milliseconds);
+
+void
+xmlrpc_client_start_rpc(xmlrpc_env *             const envP,
+                        struct xmlrpc_client *   const clientP,
+                        xmlrpc_server_info *     const serverInfoP,
+                        const char *             const methodName,
+                        xmlrpc_value *           const argP,
+                        xmlrpc_response_handler        responseHandler,
+                        void *                   const userData);
+
+void 
+xmlrpc_client_start_rpcf(xmlrpc_env *    const envP,
+                         xmlrpc_client * const clientP,
+                         const char *    const serverUrl,
+                         const char *    const methodName,
+                         xmlrpc_response_handler callback,
+                         void *          const userData,
+                         const char *    const format,
+                         ...);
+
+#include <xmlrpc-c/client_global.h>
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _XMLRPC_CLIENT_H_ */
diff --git a/include/xmlrpc-c/client.hpp b/include/xmlrpc-c/client.hpp
new file mode 100644 (file)
index 0000000..846ad9b
--- /dev/null
@@ -0,0 +1,283 @@
+#ifndef CLIENT_HPP_INCLUDED
+#define CLIENT_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <xmlrpc-c/girerr.hpp>
+#include <xmlrpc-c/girmem.hpp>
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/timeout.hpp>
+#include <xmlrpc-c/client_transport.hpp>
+
+namespace xmlrpc_c {
+
+class clientTransactionPtr;
+
+class clientTransaction : public girmem::autoObject {
+
+    friend class clientTransactionPtr;
+
+public:
+    virtual void
+    finish(xmlrpc_c::rpcOutcome const& outcome) = 0;
+    
+    virtual void
+    finishErr(girerr::error const& error) = 0;
+
+protected:
+    clientTransaction();
+};
+
+class clientTransactionPtr : public girmem::autoObjectPtr {
+    
+public:
+    clientTransactionPtr();
+
+    virtual ~clientTransactionPtr();
+
+    virtual xmlrpc_c::clientTransaction *
+    operator->() const;
+};
+
+class clientPtr;
+
+class client : public girmem::autoObject {
+/*----------------------------------------------------------------------------
+   A generic client -- a means of performing an RPC.  This is so generic
+   that it can be used for clients that are not XML-RPC.
+
+   This is a base class.  Derived classes define things such as that
+   XML and HTTP get used to perform the RPC.
+-----------------------------------------------------------------------------*/
+    friend class clientTransactionPtr;
+
+public:
+    virtual ~client();
+
+    virtual void
+    call(xmlrpc_c::carriageParm * const  carriageParmP,
+         std::string              const& methodName,
+         xmlrpc_c::paramList      const& paramList,
+         xmlrpc_c::rpcOutcome *   const  outcomeP) = 0;
+
+    virtual void
+    start(xmlrpc_c::carriageParm *       const  carriageParmP,
+          std::string                    const& methodName,
+          xmlrpc_c::paramList            const& paramList,
+          xmlrpc_c::clientTransactionPtr const& tranP);
+};
+
+class clientPtr : public girmem::autoObjectPtr {
+public:
+    clientPtr();
+
+    explicit clientPtr(xmlrpc_c::client * const clientP);
+
+    xmlrpc_c::client *
+    operator->() const;
+
+    xmlrpc_c::client *
+    get() const;
+};
+
+class serverAccessor : public girmem::autoObject {
+    
+public:
+    serverAccessor(xmlrpc_c::clientPtr       const clientP,
+                   xmlrpc_c::carriageParmPtr const carriageParmP);
+
+    void
+    call(std::string            const& methodName,
+         xmlrpc_c::paramList    const& paramList,
+         xmlrpc_c::rpcOutcome * const  outcomeP) const;
+
+private:
+    xmlrpc_c::clientPtr       const clientP;
+    xmlrpc_c::carriageParmPtr const carriageParmP;
+};
+
+class serverAccessorPtr : public girmem::autoObjectPtr {
+public:
+    serverAccessorPtr();
+
+    explicit
+    serverAccessorPtr(xmlrpc_c::serverAccessor * const serverAccessorP);
+
+    xmlrpc_c::serverAccessor *
+    operator->() const;
+
+    xmlrpc_c::serverAccessor *
+    get() const;
+};
+
+class connection {
+/*----------------------------------------------------------------------------
+   A nexus of a particular client and a particular server, along with
+   carriage parameters for performing RPCs between the two.
+
+   This is a minor convenience for client programs that always talk to
+   the same server the same way.
+
+   Use this as a parameter to rpc.call().
+-----------------------------------------------------------------------------*/
+public:
+    connection(xmlrpc_c::client *       const clientP,
+               xmlrpc_c::carriageParm * const carriageParmP);
+
+    ~connection();
+
+    xmlrpc_c::client *       clientP;
+    xmlrpc_c::carriageParm * carriageParmP;
+};
+
+class client_xml : public xmlrpc_c::client {
+/*----------------------------------------------------------------------------
+   A client that uses XML-RPC XML in the RPC.  This class does not define
+   how the XML gets transported, though (i.e. does not require HTTP).
+-----------------------------------------------------------------------------*/
+public:
+    client_xml(xmlrpc_c::clientXmlTransport * const transportP);
+
+    client_xml(xmlrpc_c::clientXmlTransportPtr const transportP);
+
+    void
+    call(carriageParm *         const  carriageParmP,
+         std::string            const& methodName,
+         xmlrpc_c::paramList    const& paramList,
+         xmlrpc_c::rpcOutcome * const  outcomeP);
+
+    void
+    start(xmlrpc_c::carriageParm *       const  carriageParmP,
+          std::string                    const& methodName,
+          xmlrpc_c::paramList            const& paramList,
+          xmlrpc_c::clientTransactionPtr const& tranP);
+
+    void
+    finishAsync(xmlrpc_c::timeout const timeout);
+
+private:
+    /* We have both kinds of pointers to give the user flexibility -- we
+       have constructors that take both.  But the simple pointer
+       'transportP' is valid in both cases.
+    */
+    xmlrpc_c::clientXmlTransport * transportP;
+    xmlrpc_c::clientXmlTransportPtr transportPtr;
+};
+
+class xmlTransaction_client : public xmlrpc_c::xmlTransaction {
+
+public:
+    xmlTransaction_client(xmlrpc_c::clientTransactionPtr const& tranP);
+
+    void
+    finish(std::string const& responseXml) const;
+
+    void
+    finishErr(girerr::error const& error) const;
+private:
+    xmlrpc_c::clientTransactionPtr const tranP;
+};
+
+class xmlTransaction_clientPtr : public xmlTransactionPtr {
+public:
+    xmlTransaction_clientPtr();
+    
+    xmlTransaction_clientPtr(xmlrpc_c::clientTransactionPtr const& tranP);
+
+    xmlrpc_c::xmlTransaction_client *
+    operator->() const;
+};
+
+class rpcPtr;
+
+class rpc : public clientTransaction {
+/*----------------------------------------------------------------------------
+   An RPC.  An RPC consists of method name, parameters, and result.  It
+   does not specify in any way how the method name and parameters get
+   turned into a result.  It does not presume XML or HTTP.
+
+   You don't create an object of this class directly.  All references to
+   an rpc object should be by an rpcPtr object.  Create a new RPC by
+   creating a new rpcPtr.  Accordingly, our constructors and destructors
+   are protected, but available to our friend class rpcPtr.
+
+   In order to do asynchronous RPCs, you normally have to create a derived
+   class that defines a useful notifyComplete().  If you do that, you'll
+   want to make sure the derived class objects get accessed only via rpcPtrs
+   as well.
+-----------------------------------------------------------------------------*/
+    friend class xmlrpc_c::rpcPtr;
+
+public:
+    void
+    call(xmlrpc_c::client       * const clientP,
+         xmlrpc_c::carriageParm * const carriageParmP);
+
+    void
+    call(xmlrpc_c::connection const& connection);
+
+    void
+    start(xmlrpc_c::client       * const clientP,
+          xmlrpc_c::carriageParm * const carriageParmP);
+    
+    void
+    start(xmlrpc_c::connection const& connection);
+    
+    void
+    finish(xmlrpc_c::rpcOutcome const& outcome);
+
+    void
+    finishErr(girerr::error const& error);
+
+    virtual void
+    notifyComplete();
+
+    bool
+    isFinished() const;
+
+    bool
+    isSuccessful() const;
+
+    xmlrpc_c::value
+    getResult() const;
+
+    xmlrpc_c::fault
+    getFault() const;
+
+    rpc(std::string         const  methodName,
+        xmlrpc_c::paramList const& paramList);
+
+    virtual ~rpc();
+
+private:
+    enum state {
+        STATE_UNFINISHED,  // RPC is running or not started yet
+        STATE_ERROR,       // We couldn't execute the RPC
+        STATE_FAILED,      // RPC executed successfully, but failed per XML-RPC
+        STATE_SUCCEEDED    // RPC is done, no exception
+    };
+    enum state state;
+    girerr::error * errorP;     // Defined only in STATE_ERROR
+    xmlrpc_c::rpcOutcome outcome;
+        // Defined only in STATE_FAILED and STATE_SUCCEEDED
+    std::string methodName;
+    xmlrpc_c::paramList paramList;
+};
+
+class rpcPtr : public clientTransactionPtr {
+public:
+    rpcPtr();
+
+    explicit rpcPtr(xmlrpc_c::rpc * const rpcP);
+
+    rpcPtr(std::string         const  methodName,
+           xmlrpc_c::paramList const& paramList);
+
+    xmlrpc_c::rpc *
+    operator->() const;
+};
+
+} // namespace
+#endif
diff --git a/include/xmlrpc-c/client_global.h b/include/xmlrpc-c/client_global.h
new file mode 100644 (file)
index 0000000..23b4e85
--- /dev/null
@@ -0,0 +1,141 @@
+#ifndef CLIENT_GLOBAL_H_INCLUDED
+#define CLIENT_GLOBAL_H_INCLUDED
+
+/*=========================================================================
+**  Initialization and Shutdown
+**=========================================================================
+**  These routines initialize and terminate the XML-RPC client. If you're
+**  already using libwww on your own, you can pass
+**  XMLRPC_CLIENT_SKIP_LIBWWW_INIT to avoid initializing it twice.
+*/
+
+#define XMLRPC_CLIENT_NO_FLAGS         (0)
+#define XMLRPC_CLIENT_SKIP_LIBWWW_INIT (1)
+
+extern void
+xmlrpc_client_init(int          const flags,
+                   const char * const appname,
+                   const char * const appversion);
+
+void 
+xmlrpc_client_init2(xmlrpc_env *                      const env,
+                    int                               const flags,
+                    const char *                      const appname,
+                    const char *                      const appversion,
+                    const struct xmlrpc_clientparms * const clientparms,
+                    unsigned int                      const parm_size);
+
+extern void
+xmlrpc_client_cleanup(void);
+
+/*=========================================================================
+**  xmlrpc_client_call
+**=========================================================================
+**  A synchronous XML-RPC client. Do not attempt to call any of these
+**  functions from inside an asynchronous callback!
+*/
+
+xmlrpc_value * 
+xmlrpc_client_call(xmlrpc_env * const envP,
+                   const char * const server_url,
+                   const char * const method_name,
+                   const char * const format,
+                   ...);
+
+xmlrpc_value * 
+xmlrpc_client_call_params(xmlrpc_env *   const envP,
+                          const char *   const serverUrl,
+                          const char *   const methodName,
+                          xmlrpc_value * const paramArrayP);
+
+xmlrpc_value * 
+xmlrpc_client_call_server(xmlrpc_env *               const envP,
+                          const xmlrpc_server_info * const server,
+                          const char *               const method_name,
+                          const char *               const format, 
+                          ...);
+
+xmlrpc_value *
+xmlrpc_client_call_server_params(
+    xmlrpc_env *               const envP,
+    const xmlrpc_server_info * const serverP,
+    const char *               const method_name,
+    xmlrpc_value *             const paramArrayP);
+
+void
+xmlrpc_client_transport_call(
+    xmlrpc_env *               const envP,
+    void *                     const reserved,  /* for client handle */
+    const xmlrpc_server_info * const serverP,
+    xmlrpc_mem_block *         const callXmlP,
+    xmlrpc_mem_block **        const respXmlPP);
+
+
+/*=========================================================================
+**  xmlrpc_client_call_asynch
+**=========================================================================
+**  An asynchronous XML-RPC client.
+*/
+
+/* Make an asynchronous XML-RPC call. We make internal copies of all
+** arguments except user_data, so you can deallocate them safely as soon
+** as you return. Errors will be passed to the callback. You will need
+** to run the event loop somehow; see below.
+** WARNING: If an error occurs while building the argument, the
+** response handler will be called with a NULL param_array. */
+void 
+xmlrpc_client_call_asynch(const char * const server_url,
+                          const char * const method_name,
+                          xmlrpc_response_handler callback,
+                          void *       const user_data,
+                          const char * const format,
+                          ...);
+
+/* As above, but use an xmlrpc_server_info object. The server object can be
+** safely destroyed as soon as this function returns. */
+void 
+xmlrpc_client_call_server_asynch(xmlrpc_server_info * const server,
+                                 const char *         const method_name,
+                                 xmlrpc_response_handler callback,
+                                 void *               const user_data,
+                                 const char *         const format,
+                                 ...);
+
+/* As above, but the parameter list is supplied as an xmlrpc_value
+** containing an array.
+*/
+void
+xmlrpc_client_call_asynch_params(const char *   const server_url,
+                                 const char *   const method_name,
+                                 xmlrpc_response_handler callback,
+                                 void *         const user_data,
+                                 xmlrpc_value * const paramArrayP);
+    
+/* As above, but use an xmlrpc_server_info object. The server object can be
+** safely destroyed as soon as this function returns. */
+void 
+xmlrpc_client_call_server_asynch_params(
+    xmlrpc_server_info * const server,
+    const char *         const method_name,
+    xmlrpc_response_handler callback,
+    void *               const user_data,
+    xmlrpc_value *       const paramArrayP);
+    
+/*=========================================================================
+**  Event Loop Interface
+**=========================================================================
+**  These functions can be used to run the XML-RPC event loop. If you
+**  don't like these, you can also run the libwww event loop directly.
+*/
+
+/* Finish all outstanding asynchronous calls. Alternatively, the loop
+** will exit if someone calls xmlrpc_client_event_loop_end. */
+extern void
+xmlrpc_client_event_loop_finish_asynch(void);
+
+
+/* Finish all outstanding asynchronous calls. */
+extern void
+xmlrpc_client_event_loop_finish_asynch_timeout(unsigned long milliseconds);
+
+#endif
diff --git a/include/xmlrpc-c/client_int.h b/include/xmlrpc-c/client_int.h
new file mode 100644 (file)
index 0000000..a7ef2bc
--- /dev/null
@@ -0,0 +1,102 @@
+/*============================================================================
+                         xmlrpc_client_int.h
+==============================================================================
+  This header file defines the interface between client modules inside
+  xmlrpc-c.
+
+  Use this in addition to xmlrpc_client.h, which defines the external
+  interface.
+
+  Copyright information is at the end of the file.
+============================================================================*/
+
+
+#ifndef  XMLRPC_CLIENT_INT_H_INCLUDED
+#define  XMLRPC_CLIENT_INT_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct _xmlrpc_server_info {
+    char *_server_url;
+    char *_http_basic_auth;
+};
+
+/* Create a new server info record, with a copy of the old server. */
+extern xmlrpc_server_info * 
+xmlrpc_server_info_copy(xmlrpc_env *env, xmlrpc_server_info *aserver);
+
+
+/*=========================================================================
+** Transport Implementation functions.
+**=========================================================================
+*/
+#include "xmlrpc-c/transport.h"
+
+/* The generalized event loop. This uses the above flags. For more details,
+** see the wrapper functions below. If you're not using the timeout, the
+** 'milliseconds' parameter will be ignored.
+** Note that ANY event loop call will return immediately if there are
+** no outstanding XML-RPC calls. */
+extern void
+xmlrpc_client_event_loop_run_general (int flags, xmlrpc_timeout milliseconds);
+
+/* Run the event loop forever. The loop will exit if someone calls
+** xmlrpc_client_event_loop_end. */
+extern void
+xmlrpc_client_event_loop_run (void);
+
+/* Run the event loop forever. The loop will exit if someone calls
+** xmlrpc_client_event_loop_end or the timeout expires.
+** (Note that ANY event loop call will return immediately if there are
+** no outstanding XML-RPC calls.) */
+extern void
+xmlrpc_client_event_loop_run_timeout (xmlrpc_timeout milliseconds);
+
+/* End the running event loop immediately. This can also be accomplished
+** by calling the corresponding function in libwww.
+** (Note that ANY event loop call will return immediately if there are
+** no outstanding XML-RPC calls.) */
+extern void
+xmlrpc_client_event_loop_end (void);
+
+
+/* Return true if there are uncompleted asynchronous calls.
+** The exact value of this during a response callback is undefined. */
+extern int
+xmlrpc_client_asynch_calls_are_unfinished (void);
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+
+
+
diff --git a/include/xmlrpc-c/client_simple.hpp b/include/xmlrpc-c/client_simple.hpp
new file mode 100644 (file)
index 0000000..52e6c2b
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef CLIENT_SIMPLE_HPP_INCLUDED
+#define CLIENT_SIMPLE_HPP_INCLUDED
+
+#include <string>
+
+#include <xmlrpc-c/base.hpp>
+#include <xmlrpc-c/client.hpp>
+
+namespace xmlrpc_c {
+
+
+class clientSimple {
+
+public:
+    clientSimple();
+
+    void
+    call(std::string       const serverUrl,
+         std::string       const methodName,
+         xmlrpc_c::value * const resultP);
+
+    void
+    call(std::string       const serverUrl,
+         std::string       const methodName,
+         std::string       const format,
+         xmlrpc_c::value * const resultP,
+         ...);
+
+    void
+    call(std::string         const  serverUrl,
+         std::string         const  methodName,
+         xmlrpc_c::paramList const& paramList,
+         xmlrpc_c::value *   const  resultP);
+
+private:
+    xmlrpc_c::clientPtr clientP;
+};
+
+} // namespace
+#endif
+
+
+
+
diff --git a/include/xmlrpc-c/client_transport.hpp b/include/xmlrpc-c/client_transport.hpp
new file mode 100644 (file)
index 0000000..f16cac0
--- /dev/null
@@ -0,0 +1,342 @@
+#ifndef CLIENT_TRANSPORT_HPP_INCLUDED
+#define CLIENT_TRANSPORT_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+#include <xmlrpc-c/util.h>
+#include <xmlrpc-c/client.h>
+#include <xmlrpc-c/girerr.hpp>
+#include <xmlrpc-c/girmem.hpp>
+#include <xmlrpc-c/timeout.hpp>
+
+namespace xmlrpc_c {
+
+class carriageParmPtr;
+
+class carriageParm : public girmem::autoObject {
+/*----------------------------------------------------------------------------
+   The parameter to a client for an individual RPC.  It tells specifics
+   of how to carry the call to the server and the response back.  For
+   example, it may identify the server.  It may identify communication
+   protocols to use.  It may indicate permission and accounting
+   information.
+
+   This is a base class; the carriage parameter is specific to the
+   class of client.  For example, an HTTP-based client would have a
+   URL and HTTP basic authentication info as parameter.
+-----------------------------------------------------------------------------*/
+protected:
+    virtual ~carriageParm();
+    carriageParm();
+};
+
+class carriageParmPtr : public girmem::autoObjectPtr {
+
+public:
+    carriageParmPtr();
+
+    explicit carriageParmPtr(xmlrpc_c::carriageParm * const carriageParmP);
+
+    xmlrpc_c::carriageParm *
+    operator->() const;
+
+    xmlrpc_c::carriageParm *
+    get() const;
+};
+
+class carriageParm_http0 : public xmlrpc_c::carriageParm {
+
+public:
+    carriageParm_http0(std::string const serverUrl);
+
+    ~carriageParm_http0();
+
+    void
+    setBasicAuth(std::string const userid,
+                 std::string const password);
+
+    xmlrpc_server_info * c_serverInfoP;
+
+protected:
+    // Only a derived class is allowed to create an object with no
+    // server URL, and the derived class is expected to follow it up
+    // with an instantiate() to establish the server URL.
+
+    carriageParm_http0();
+
+    void
+    instantiate(std::string const serverUrl);
+};
+
+class carriageParm_http0Ptr : public xmlrpc_c::carriageParmPtr {
+
+public:
+    carriageParm_http0Ptr();
+    carriageParm_http0Ptr(xmlrpc_c::carriageParm_http0 * const carriageParmP);
+
+    xmlrpc_c::carriageParm_http0 *
+    operator->() const;
+};
+
+class carriageParm_curl0 : public xmlrpc_c::carriageParm_http0 {
+
+public:
+    carriageParm_curl0(std::string const serverUrl);
+
+};
+
+class carriageParm_curl0Ptr : public xmlrpc_c::carriageParm_http0Ptr {
+
+public:
+    carriageParm_curl0Ptr();
+    carriageParm_curl0Ptr(xmlrpc_c::carriageParm_curl0 * const carriageParmP);
+
+    xmlrpc_c::carriageParm_curl0 *
+    operator->() const;
+};
+
+class carriageParm_libwww0 : public xmlrpc_c::carriageParm_http0 {
+
+public:
+    carriageParm_libwww0(std::string const serverUrl);
+
+};
+
+class carriageParm_libwww0Ptr : public xmlrpc_c::carriageParm_http0Ptr {
+
+public:
+    carriageParm_libwww0Ptr();
+    carriageParm_libwww0Ptr(xmlrpc_c::carriageParm_libwww0 * const);
+
+    xmlrpc_c::carriageParm_libwww0 *
+    operator->() const;
+};
+
+class carriageParm_wininet0 : public xmlrpc_c::carriageParm_http0 {
+
+public:
+    carriageParm_wininet0(std::string const serverUrl);
+
+};
+
+class carriageParm_wininet0Ptr : public xmlrpc_c::carriageParm_http0Ptr {
+
+public:
+    carriageParm_wininet0Ptr();
+    carriageParm_wininet0Ptr(xmlrpc_c::carriageParm_wininet0 * const);
+
+    xmlrpc_c::carriageParm_wininet0 *
+    operator->() const;
+};
+
+//----------------------------------------------------------------------------
+
+class xmlTransactionPtr;
+
+class xmlTransaction : public girmem::autoObject {
+
+    friend class xmlTransactionPtr;
+
+public:
+    virtual void
+    finish(std::string const& responseXml) const;
+
+    virtual void
+    finishErr(girerr::error const& error) const;
+
+protected:
+    xmlTransaction();
+};
+
+class xmlTransactionPtr : public girmem::autoObjectPtr {
+public:
+    xmlTransactionPtr();
+
+    xmlrpc_c::xmlTransaction *
+    operator->() const;
+};
+
+//----------------------------------------------------------------------------
+
+class clientXmlTransport : public girmem::autoObject {
+/*----------------------------------------------------------------------------
+   An object which transports XML to and from an XML-RPC server for an
+   XML-RPC client.
+
+   This is a base class.  Derived classes define methods to perform the
+   transportation in particular ways.
+-----------------------------------------------------------------------------*/
+public:
+    virtual ~clientXmlTransport();
+
+    virtual void
+    call(xmlrpc_c::carriageParm * const  carriageParmP,
+         std::string              const& callXml,
+         std::string *            const  responseXmlP) = 0;
+
+    virtual void
+    start(xmlrpc_c::carriageParm *    const  carriageParmP,
+          std::string                 const& callXml,
+          xmlrpc_c::xmlTransactionPtr const& xmlTranP);
+
+    virtual void
+    finishAsync(xmlrpc_c::timeout const timeout);
+
+    static void
+    asyncComplete(
+        struct xmlrpc_call_info * const callInfoP,
+        xmlrpc_mem_block *        const responseXmlMP,
+        xmlrpc_env                const transportEnv);
+};
+
+class clientXmlTransportPtr : public girmem::autoObjectPtr {
+    
+public:
+    clientXmlTransportPtr();
+
+    clientXmlTransportPtr(xmlrpc_c::clientXmlTransport * const transportP);
+
+    xmlrpc_c::clientXmlTransport *
+    operator->() const;
+
+    xmlrpc_c::clientXmlTransport *
+    get() const;
+};
+
+class clientXmlTransport_http : public xmlrpc_c::clientXmlTransport {
+/*----------------------------------------------------------------------------
+   A base class for client XML transports that use the simple, classic
+   C HTTP transports.
+-----------------------------------------------------------------------------*/
+public:
+    virtual ~clientXmlTransport_http();
+    
+    void
+    call(xmlrpc_c::carriageParm * const  carriageParmP,
+         std::string              const& callXml,
+         std::string *            const  responseXmlP);
+    
+    void
+    start(xmlrpc_c::carriageParm *    const  carriageParmP,
+          std::string                 const& callXml,
+          xmlrpc_c::xmlTransactionPtr const& xmlTranP);
+        
+    virtual void
+    finishAsync(xmlrpc_c::timeout const timeout);
+
+    static std::vector<std::string>
+    availableTypes();
+
+    static clientXmlTransportPtr
+    create();
+
+protected:
+    clientXmlTransport_http() {} // ensure no one can create
+    struct xmlrpc_client_transport *           c_transportP;
+    const struct xmlrpc_client_transport_ops * c_transportOpsP;
+};
+
+
+class clientXmlTransport_curl : public xmlrpc_c::clientXmlTransport_http {
+
+public:
+    class constrOpt {
+    public:
+        constrOpt();
+
+        constrOpt & network_interface (std::string const& arg);
+        constrOpt & no_ssl_verifypeer (bool        const& arg);
+        constrOpt & no_ssl_verifyhost (bool        const& arg);
+        constrOpt & user_agent        (std::string const& arg);
+        constrOpt & ssl_cert          (std::string const& arg);
+        constrOpt & sslcerttype       (std::string const& arg);
+        constrOpt & sslcertpasswd     (std::string const& arg);
+        constrOpt & sslkey            (std::string const& arg);
+        constrOpt & sslkeytype        (std::string const& arg);
+        constrOpt & sslkeypasswd      (std::string const& arg);
+        constrOpt & sslengine         (std::string const& arg);
+        constrOpt & sslengine_default (bool        const& arg);
+        constrOpt & sslversion        (xmlrpc_sslversion const& arg);
+        constrOpt & cainfo            (std::string const& arg);
+        constrOpt & capath            (std::string const& arg);
+        constrOpt & randomfile        (std::string const& arg);
+        constrOpt & egdsocket         (std::string const& arg);
+        constrOpt & ssl_cipher_list   (std::string const& arg);
+
+        struct {
+            std::string network_interface;
+            bool        no_ssl_verifypeer;
+            bool        no_ssl_verifyhost;
+            std::string user_agent;
+            std::string ssl_cert;
+            std::string sslcerttype;
+            std::string sslcertpasswd;
+            std::string sslkey;
+            std::string sslkeytype;
+            std::string sslkeypasswd;
+            std::string sslengine;
+            bool        sslengine_default;
+            xmlrpc_sslversion sslversion;
+            std::string cainfo;
+            std::string capath;
+            std::string randomfile;
+            std::string egdsocket;
+            std::string ssl_cipher_list;
+        } value;
+        struct {
+            bool network_interface;
+            bool no_ssl_verifypeer;
+            bool no_ssl_verifyhost;
+            bool user_agent;
+            bool ssl_cert;
+            bool sslcerttype;
+            bool sslcertpasswd;
+            bool sslkey;
+            bool sslkeytype;
+            bool sslkeypasswd;
+            bool sslengine;
+            bool sslengine_default;
+            bool sslversion;
+            bool cainfo;
+            bool capath;
+            bool randomfile;
+            bool egdsocket;
+            bool ssl_cipher_list;
+        } present;
+    };
+
+    clientXmlTransport_curl(constrOpt const& opt);
+
+    clientXmlTransport_curl(std::string const networkInterface = "",
+                            bool        const noSslVerifyPeer = false,
+                            bool        const noSslVerifyHost = false,
+                            std::string const userAgent = "");
+
+    ~clientXmlTransport_curl();
+
+private:
+    void
+    initialize(constrOpt const& opt);
+};
+
+class clientXmlTransport_libwww : public xmlrpc_c::clientXmlTransport_http {
+    
+public:
+    clientXmlTransport_libwww(std::string const appname = "",
+                              std::string const appversion = "");
+
+    ~clientXmlTransport_libwww();
+};
+
+class clientXmlTransport_wininet : public xmlrpc_c::clientXmlTransport_http {
+
+public:
+    clientXmlTransport_wininet(bool const allowInvalidSslCerts = false);
+
+    ~clientXmlTransport_wininet();
+};
+
+
+
+} // namespace
+#endif
diff --git a/include/xmlrpc-c/girerr.hpp b/include/xmlrpc-c/girerr.hpp
new file mode 100644 (file)
index 0000000..1008722
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef GIRERR_HPP_INCLUDED
+#define GIRERR_HPP_INCLUDED
+
+#include <string>
+#include <exception>
+
+#define HAVE_GIRERR_ERROR
+
+namespace girerr {
+
+class error : public std::exception {
+public:
+    error(std::string const& what_arg) : _what(what_arg) {}
+
+    ~error() throw() {}
+
+    virtual const char *
+    what() const throw() { return this->_what.c_str(); };
+
+private:
+    std::string _what;
+};
+
+// throwf() always throws a girerr::error .
+
+void
+throwf(const char * const format, ...);
+
+} // namespace
+
+#endif
diff --git a/include/xmlrpc-c/girmem.hpp b/include/xmlrpc-c/girmem.hpp
new file mode 100644 (file)
index 0000000..0113046
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef GIRMEM_HPP_INCLUDED
+#define GIRMEM_HPP_INCLUDED
+
+
+/* The following pthread crap mirrors what is in pthreadx.h, which is
+   what girmem.cpp uses to declare the lock interface.  We can't simply
+   include pthreadx.h here, because it's an internal Xmlrpc-c header file,
+   and this is an external one.
+
+   This is a stopgap measure until we do something cleaner, such as expose
+   pthreadx.h as an external interface (class girlock, maybe?) or create
+   a lock class with virtual methods.
+
+   The problem we're solving is that class autoObject contains 
+   a pthread_mutex_t member, and on Windows, there's no such type.
+*/
+   
+#ifndef WIN32
+#  include <pthread.h>
+   typedef pthread_mutex_t girmem_lock;
+#else
+   typedef CRITICAL_SECTION girmem_lock;
+#endif
+
+namespace girmem {
+
+class autoObjectPtr;
+
+class autoObject {
+    friend class autoObjectPtr;
+
+public:
+    void incref();
+    void decref(bool * const unreferencedP);
+    
+protected:
+    autoObject();
+    virtual ~autoObject();
+
+private:
+    girmem_lock refcountLock;
+    unsigned int refcount;
+};
+
+class autoObjectPtr {
+public:
+    autoObjectPtr();
+    autoObjectPtr(girmem::autoObject * objectP);
+    autoObjectPtr(girmem::autoObjectPtr const& autoObjectPtr);
+    
+    ~autoObjectPtr();
+    
+    void
+    point(girmem::autoObject * const objectP);
+
+    void
+    unpoint();
+
+    autoObjectPtr
+    operator=(girmem::autoObjectPtr const& objectPtr);
+    
+    girmem::autoObject *
+    operator->() const;
+    
+    girmem::autoObject *
+    get() const;
+
+protected:
+    girmem::autoObject * objectP;
+};
+
+} // namespace
+
+#endif
diff --git a/include/xmlrpc-c/oldcppwrapper.hpp b/include/xmlrpc-c/oldcppwrapper.hpp
new file mode 100644 (file)
index 0000000..22bc9c5
--- /dev/null
@@ -0,0 +1,419 @@
+// -*- C++ -*-   <-- an Emacs control
+
+// Copyright information is at the bottom of the file.
+
+//=========================================================================
+//  XML-RPC C++ API
+//=========================================================================
+
+
+#ifndef XMLRPCCPP_H_INCLUDED
+#define XMLRPCCPP_H_INCLUDED
+
+// There used to be a "using namespace std" here and some confusing old
+// comments about it having something to do with what header file you
+// include to get string functions.
+//
+// "using namespace std" was under "#if defined(__GNUC__) && (__GNUC__ >= 3)"
+// until December 2003, and then unconditional until Release 1.1 (March 2005).
+// Older GNU Compilers apparently imply namespace std, so they don't need it.
+// 
+// But "using namespace std" is a bad idea.  This is an interface header
+// file, and we don't want to suck all of namespace std into the user's
+// namespace just because he's using Xmlrpc-c.  So we took it out.
+// We refer to std names like std::string.
+// -Bryan 2005.03.12.
+
+
+#include <cstdlib>
+#include <string>
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+#include <xmlrpc-c/server.h>
+
+
+//=========================================================================
+//  XmlRpcFault
+//=========================================================================
+//  A C++ exception class representing an XML-RPC fault.
+
+class XmlRpcFault {
+
+private:
+    xmlrpc_env   mFault;
+
+    XmlRpcFault& operator= (XmlRpcFault const& f)
+        { if (true || f.getFaultCode()) abort(); return (XmlRpcFault&) f; }
+
+public:
+    XmlRpcFault (const XmlRpcFault &fault);
+    XmlRpcFault (const int faultCode, const std::string faultString);
+    XmlRpcFault (const xmlrpc_env *env);
+    ~XmlRpcFault (void);
+
+    int          getFaultCode (void) const;
+    std::string  getFaultString (void) const;
+    xmlrpc_env  *getFaultEnv (void);
+};
+
+inline int XmlRpcFault::getFaultCode (void) const {
+    return mFault.fault_code;
+}
+
+inline xmlrpc_env *XmlRpcFault::getFaultEnv (void) {
+    return &mFault;
+}
+
+
+//=========================================================================
+//  XmlRpcEnv
+//=========================================================================
+//  This class can be used to wrap xmlrpc_env object. Use it as follows:
+//
+//    XmlRpcEnv env;
+//    xmlrpc_parse_value(env, v, "(i)", &i);
+//    env.throwIfFaultOccurred();        
+
+class XmlRpcEnv {
+
+private:
+    xmlrpc_env   mEnv;
+
+    void         throwMe (void) const;
+    XmlRpcEnv&   operator= (XmlRpcEnv const& e)
+        { if (true || e.faultOccurred()) abort(); return (XmlRpcEnv&) e;}
+
+public:
+    XmlRpcEnv (const XmlRpcEnv &env);
+    XmlRpcEnv (void) { xmlrpc_env_init(&mEnv); }
+    ~XmlRpcEnv (void) { xmlrpc_env_clean(&mEnv); }
+    
+    bool         faultOccurred (void) const { return mEnv.fault_occurred; };
+    bool         hasFaultOccurred (void) const { return faultOccurred(); };
+        /* hasFaultOccurred() is for backward compatibility.
+           faultOccurred() is a superior name for this.
+        */
+    std::string  getFaultString() const { return mEnv.fault_string; };
+    XmlRpcFault  getFault (void) const;
+
+    void         throwIfFaultOccurred (void) const;
+
+    operator xmlrpc_env * (void) { return &mEnv; }
+};
+
+inline void XmlRpcEnv::throwIfFaultOccurred (void) const {
+    if (faultOccurred())
+        throwMe();
+}
+
+
+//=========================================================================
+//  XmlRpcValue
+//=========================================================================
+//  An object in this class is an XML-RPC value.
+//
+//  We have a complex structure to allow C code mixed in with C++ code
+//  which uses this class to refer to the same XML-RPC value object.
+//  This is especially important because there aren't proper C++ facilities
+//  for much of Xmlrpc-c; you have to use the C facilities even if you'd
+//  rather use proper C++.
+//
+//  The XmlRpcValue object internally represents the value as an
+//  xmlrpc_value.  It holds one reference to the xmlrpc_value.  Users
+//  of XmlRpcValue never see that xmlrpc_value, but C code can.  the
+//  C code might create the xmlrpc_value and then bind it to an XmlRpcValue,
+//  or it might get the xmlrpc_value handle from the XmlRpcValue.  Finally,
+//  C code can simply use the XmlRpcValue where an xmlrpc_value handle is
+//  required and it gets converted automatically.
+//
+//  So reference counting for the xmlrpc_value is quite a nightmare.
+
+class XmlRpcValue {
+
+private:
+    xmlrpc_value *mValue;
+
+public:
+    enum ReferenceBehavior {
+        MAKE_REFERENCE,
+        CONSUME_REFERENCE
+    };
+
+    typedef xmlrpc_int32 int32;
+    
+    XmlRpcValue (void);
+    XmlRpcValue (xmlrpc_value *value,
+                 ReferenceBehavior behavior = MAKE_REFERENCE);
+    XmlRpcValue (const XmlRpcValue& value);
+    ~XmlRpcValue (void);
+    
+    XmlRpcValue&  operator= (const XmlRpcValue& value);
+
+    // Accessing the value's type (think of this as lightweight RTTI).
+    xmlrpc_type getType(void) const;
+    
+    // We don't supply an automatic conversion operator--you need to say
+    // whether you want to make or borrow this object's reference.
+    // XXX - Is it really OK for these to be const?
+    xmlrpc_value *makeReference (void) const;
+    xmlrpc_value *borrowReference (void) const;
+
+    // Some static "constructor" functions.
+    static XmlRpcValue makeInt      (const XmlRpcValue::int32 i);
+    static XmlRpcValue makeBool     (const bool b);
+    static XmlRpcValue makeDouble   (const double d);
+    static XmlRpcValue makeDateTime (const std::string& dateTime);
+    static XmlRpcValue makeString   (const std::string& str);
+    static XmlRpcValue makeString   (const char *const str);
+    static XmlRpcValue makeString   (const char *const str, size_t len);
+    static XmlRpcValue makeArray    (void);
+    static XmlRpcValue makeStruct   (void);
+    static XmlRpcValue makeBase64   (const unsigned char *const data,
+                                     size_t len);
+    /*
+    // An interface to xmlrpc_build_value.
+    static XmlRpcValue buildValue (const char *const format, ...);
+    */
+
+    // Some functions to get the underlying data.
+    // These will throw an XmlRpcFault if the data is the wrong type.
+    XmlRpcValue::int32 getInt   (void) const;
+    bool         getBool        (void) const;
+    double       getDouble      (void) const;
+    std::string  getRawDateTime (void) const;
+    std::string  getString      (void) const;
+    XmlRpcValue  getArray       (void) const;
+    XmlRpcValue  getStruct      (void) const;
+
+    // This returns an internal pointer which will become invalid when
+    // all references to the underlying value are destroyed.
+    void         getBase64      (const unsigned char *& out_data,
+                                 size_t& out_len) const;
+
+    /*
+    // An interface to xmlrpc_parse_value.
+    void parseValue (const char *const format, ...);
+    */
+
+    // Array functions. These will throw an XmlRpcFault if the value
+    // isn't an array.
+    size_t       arraySize (void) const;
+    void         arrayAppendItem (const XmlRpcValue& value);
+    XmlRpcValue  arrayGetItem (int index) const;
+    
+    // Struct functions. These will throw an XmlRpcFault if the value
+    // isn't a struct.
+    size_t       structSize (void) const;
+    bool         structHasKey (const std::string& key) const;
+    XmlRpcValue  structGetValue (const std::string& key) const;
+    void         structSetValue (const std::string& key, 
+                                 const XmlRpcValue& value);
+    void         structGetKeyAndValue (const int index,
+                                       std::string& out_key,
+                                       XmlRpcValue& out_value) const;
+};
+
+inline XmlRpcValue::XmlRpcValue (xmlrpc_value *value,
+                                 ReferenceBehavior behavior) 
+{
+    mValue = value;
+
+    if (behavior == MAKE_REFERENCE)
+        xmlrpc_INCREF(value);
+}
+
+inline XmlRpcValue::XmlRpcValue (const XmlRpcValue& value) {
+    mValue = value.mValue;
+    xmlrpc_INCREF(mValue);
+}
+
+inline XmlRpcValue::~XmlRpcValue (void) {
+    xmlrpc_DECREF(mValue);
+}
+
+inline XmlRpcValue& XmlRpcValue::operator= (const XmlRpcValue& value) {
+    // Must increment before we decrement, in case of assignment to self.
+    xmlrpc_INCREF(value.mValue);
+    xmlrpc_DECREF(mValue);
+    mValue = value.mValue;
+    return *this;
+}
+
+inline xmlrpc_type XmlRpcValue::getType (void) const {
+    return xmlrpc_value_type(mValue);
+}
+
+inline xmlrpc_value *XmlRpcValue::makeReference (void) const {
+    xmlrpc_INCREF(mValue);
+    return mValue;
+}
+
+inline xmlrpc_value *XmlRpcValue::borrowReference (void) const {
+    return mValue;
+}
+
+
+//=========================================================================
+//  XmlRpcClient
+//=========================================================================
+
+class XmlRpcClient {
+
+private:
+    std::string mServerUrl;
+
+public:
+    static void Initialize (std::string appname, std::string appversion);
+    static void Terminate (void);
+
+    XmlRpcClient (const std::string& server_url) : mServerUrl(server_url) {}
+    ~XmlRpcClient (void) {}
+
+    XmlRpcClient (const XmlRpcClient& client);
+    XmlRpcClient& operator= (const XmlRpcClient& client);
+
+    XmlRpcValue call (std::string method_name, XmlRpcValue param_array);
+    void call_asynch (std::string method_name,
+                      XmlRpcValue param_array,
+                      xmlrpc_response_handler callback,
+                      void* user_data);
+    void event_loop_asynch (unsigned long milliseconds);
+};
+
+inline void XmlRpcClient::call_asynch(std::string method_name,
+                                      XmlRpcValue param_array,
+                                      xmlrpc_response_handler callback,
+                                      void* user_data)
+{
+    xmlrpc_client_call_asynch_params(
+        mServerUrl.c_str(),
+        method_name.c_str(),
+        callback,
+        user_data,
+        param_array.borrowReference());
+}
+
+inline void XmlRpcClient::event_loop_asynch(unsigned long milliseconds)
+{
+    xmlrpc_client_event_loop_finish_asynch_timeout(milliseconds);
+}
+
+
+//=========================================================================
+//  XmlRpcClient Methods
+//=========================================================================
+//  These are inline for now, so we don't need to screw with linker issues
+//  and build a separate client library.
+
+inline XmlRpcClient::XmlRpcClient (const XmlRpcClient& client)
+    : mServerUrl(client.mServerUrl)
+{
+}
+
+inline XmlRpcClient& XmlRpcClient::operator= (const XmlRpcClient& client) {
+    if (this != &client)
+        mServerUrl = client.mServerUrl;
+    return *this;
+}
+
+inline void XmlRpcClient::Initialize (std::string appname, 
+                                      std::string appversion) {
+    xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS,
+                       appname.c_str(),
+                       appversion.c_str());
+}
+
+inline void XmlRpcClient::Terminate (void) {
+    xmlrpc_client_cleanup();
+}
+
+inline XmlRpcValue XmlRpcClient::call (std::string method_name,
+                                       XmlRpcValue param_array)
+{
+    XmlRpcEnv env;
+    xmlrpc_value *result =
+    xmlrpc_client_call_params(env,
+                              mServerUrl.c_str(),
+                              method_name.c_str(),
+                              param_array.borrowReference());
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(result, XmlRpcValue::CONSUME_REFERENCE);
+}
+
+//=========================================================================
+//  XmlRpcGenSrv
+//=========================================================================
+
+class XmlRpcGenSrv {
+
+private:
+
+    xmlrpc_registry*    mRegistry;
+
+    xmlrpc_mem_block* alloc (XmlRpcEnv& env, const std::string& body) const; 
+
+public:
+
+    XmlRpcGenSrv (int flags);
+    ~XmlRpcGenSrv (void);
+
+    xmlrpc_registry* getRegistry (void) const;
+
+    XmlRpcGenSrv&   addMethod (const std::string& name,
+                               xmlrpc_method method,
+                               void *data);
+    XmlRpcGenSrv&   addMethod (const std::string& name,
+                               xmlrpc_method method,
+                               void* data,
+                               const std::string& signature,
+                               const std::string& help);
+    
+    std::string handle (const std::string& body) const;
+};
+
+inline XmlRpcGenSrv::XmlRpcGenSrv (int) {
+
+    XmlRpcEnv env;
+
+    mRegistry = xmlrpc_registry_new (env);
+    env.throwIfFaultOccurred();        
+}
+
+inline XmlRpcGenSrv::~XmlRpcGenSrv (void) {
+
+    xmlrpc_registry_free (mRegistry);
+}
+
+inline xmlrpc_registry* XmlRpcGenSrv::getRegistry () const {
+
+    return mRegistry;
+}
+
+
+// Copyright (C) 2001 by Eric Kidd. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. The name of the author may not be used to endorse or promote products
+//    derived from this software without specific prior written permission. 
+//  
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+
+
+#endif /* _XMLRPCCPP_H_ */
diff --git a/include/xmlrpc-c/oldxmlrpc.h b/include/xmlrpc-c/oldxmlrpc.h
new file mode 100644 (file)
index 0000000..2a5d3bf
--- /dev/null
@@ -0,0 +1,2 @@
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/server.h>
diff --git a/include/xmlrpc-c/registry.hpp b/include/xmlrpc-c/registry.hpp
new file mode 100644 (file)
index 0000000..1f12f1a
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef REGISTRY_HPP_INCLUDED
+#define REGISTRY_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+#include <list>
+
+#include <xmlrpc-c/server.h>
+#include <xmlrpc-c/girmem.hpp>
+#include <xmlrpc-c/base.hpp>
+
+namespace xmlrpc_c {
+
+
+class method : public girmem::autoObject {
+/*----------------------------------------------------------------------------
+   An XML-RPC method.
+
+   This base class is abstract.  You can't create an object in it.
+   Define a useful method with this as a base class, with an
+   execute() method.
+-----------------------------------------------------------------------------*/
+public:
+    method();
+
+    virtual ~method();
+
+    virtual void
+    execute(xmlrpc_c::paramList const& paramList,
+            xmlrpc_c::value *   const  resultP) = 0;
+
+    std::string signature() const { return _signature; };
+    std::string help() const { return _help; };
+
+protected:
+    std::string _signature;
+    std::string _help;
+};
+
+/* Example of a specific method class:
+
+   class sample_add : public xmlrpc_c::method {
+   public:
+       sample_add() {
+           this->_signature = "ii";
+           this->_help = "This method adds two integers together";
+       }
+       void
+       execute(xmlrpc_c::param_list    const paramList,
+               const xmlrpc_c::value * const retvalP) {
+          
+           int const addend(paramList.getInt(0));
+           int const adder(paramList.getInt(1));
+
+           *retvalP = xmlrpc_c::value(addend, adder);
+      }
+   };
+
+
+   Example of creating such a method:
+
+   methodPtr const sampleAddMethodP(new sample_add);
+
+   You pass around, copy, etc. the handle sampleAddMethodP and when
+   the last copy of the handle is gone, the sample_add object itself
+   gets deleted.
+
+*/
+
+
+class methodPtr : public girmem::autoObjectPtr {
+
+public:
+    methodPtr(xmlrpc_c::method * const methodP);
+
+    xmlrpc_c::method *
+    operator->() const;
+};
+
+class defaultMethod : public girmem::autoObject {
+
+public:
+    virtual ~defaultMethod();
+
+    virtual void
+    execute(std::string         const& methodName,
+            xmlrpc_c::paramList const& paramList,
+            xmlrpc_c::value *   const  resultP) = 0;
+};
+
+class defaultMethodPtr : public girmem::autoObjectPtr {
+
+public:
+    defaultMethodPtr();
+
+    defaultMethodPtr(xmlrpc_c::defaultMethod * const methodP);
+
+    xmlrpc_c::defaultMethod *
+    operator->() const;
+
+    xmlrpc_c::defaultMethod *
+    get() const;
+};
+
+class registry : public girmem::autoObject {
+/*----------------------------------------------------------------------------
+   An Xmlrpc-c server method registry.  An Xmlrpc-c server transport
+   (e.g.  an HTTP server) uses this object to process an incoming
+   Xmlrpc-c call.
+-----------------------------------------------------------------------------*/
+
+public:
+
+    registry();
+    ~registry();
+
+    void
+    addMethod(std::string         const name,
+              xmlrpc_c::methodPtr const methodP);
+
+    void
+    setDefaultMethod(xmlrpc_c::defaultMethodPtr const methodP);
+
+    void
+    disableIntrospection();
+    
+    void
+    processCall(std::string   const& body,
+                std::string * const  responseP) const;
+
+    xmlrpc_registry *
+    c_registry() const;
+        /* This is meant to be private except to other objects in the
+           Xmlrpc-c library.
+        */
+
+private:
+
+    xmlrpc_registry * c_registryP;
+        /* Pointer to the C registry object we use to implement this
+           object.
+        */
+
+    std::list<xmlrpc_c::methodPtr> methodList;
+        /* This is a list of all the method objects (actually, pointers
+           to them).  But since the real registry is the C registry object,
+           all this list is for is to maintain references to the objects
+           to which the C registry points so that they continue to exist.
+        */
+    xmlrpc_c::defaultMethodPtr defaultMethodP;
+        /* The real identifier of the default method is the C registry
+           object; this member exists only to maintain a reference to the
+           object to which the C registry points so that it will continue
+           to exist.
+        */
+};
+
+
+class registryPtr : public girmem::autoObjectPtr {
+
+public:
+    registryPtr();
+
+    registryPtr(xmlrpc_c::registry * const registryP);
+
+    xmlrpc_c::registry *
+    operator->() const;
+
+    xmlrpc_c::registry *
+    get() const;
+};
+
+} // namespace
+
+#endif
diff --git a/include/xmlrpc-c/server.h b/include/xmlrpc-c/server.h
new file mode 100644 (file)
index 0000000..adb2aaa
--- /dev/null
@@ -0,0 +1,122 @@
+/* Copyright and license information is at the end of the file */
+
+#ifndef  XMLRPC_SERVER_H_INCLUDED
+#define  XMLRPC_SERVER_H_INCLUDED
+
+#include <xmlrpc-c/base.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _xmlrpc_registry xmlrpc_registry;
+
+typedef void
+(*xmlrpc_preinvoke_method)(xmlrpc_env *   const envP,
+                           const char *   const methodName,
+                           xmlrpc_value * const paramArrayP,
+                           void *         const userData);
+
+typedef xmlrpc_value *
+(*xmlrpc_method)(xmlrpc_env *   const envP,
+                 xmlrpc_value * const paramArrayP,
+                 void *         const userData);
+
+typedef xmlrpc_value *
+(*xmlrpc_default_method)(xmlrpc_env *   const envP,
+                         const char *   const host,
+                         const char *   const methodName,
+                         xmlrpc_value * const paramArrayP,
+                         void *         const userData);
+
+xmlrpc_registry *
+xmlrpc_registry_new(xmlrpc_env * const envP);
+
+void
+xmlrpc_registry_free(xmlrpc_registry * const registryP);
+
+void
+xmlrpc_registry_disable_introspection(xmlrpc_registry * const registryP);
+
+void
+xmlrpc_registry_add_method(xmlrpc_env *      const envP,
+                           xmlrpc_registry * const registryP,
+                           const char *      const host,
+                           const char *      const methodName,
+                           xmlrpc_method     const method,
+                           void *            const userData);
+
+void
+xmlrpc_registry_add_method_w_doc(xmlrpc_env *      const envP,
+                                 xmlrpc_registry * const registryP,
+                                 const char *      const host,
+                                 const char *      const methodName,
+                                 xmlrpc_method     const method,
+                                 void *            const userData,
+                                 const char *      const signature,
+                                 const char *      const help);
+
+void
+xmlrpc_registry_set_default_method(xmlrpc_env *          const envP,
+                                   xmlrpc_registry *     const registryP,
+                                   xmlrpc_default_method const handler,
+                                   void *                const userData);
+
+void
+xmlrpc_registry_set_preinvoke_method(xmlrpc_env *            const envP,
+                                     xmlrpc_registry *       const registryP,
+                                     xmlrpc_preinvoke_method const method,
+                                     void *                  const userData);
+
+
+typedef void xmlrpc_server_shutdown_fn(xmlrpc_env *, void *, const char *);
+    /* A function that shuts down a server that uses a registry.
+       Second argument is context specific to that function; third
+       argument is a comment to describe the shutdown.
+    */
+
+void
+xmlrpc_registry_set_shutdown(xmlrpc_registry *           const registryP,
+                             xmlrpc_server_shutdown_fn * const shutdownFn,
+                             void *                      const context);
+
+/*----------------------------------------------------------------------------
+   Lower interface -- services to be used by an HTTP request handler
+-----------------------------------------------------------------------------*/
+                    
+xmlrpc_mem_block *
+xmlrpc_registry_process_call(xmlrpc_env *      const envP,
+                             xmlrpc_registry * const registryP,
+                             const char *      const host,
+                             const char *      const xmlData,
+                             size_t            const xmlLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+#endif
diff --git a/include/xmlrpc-c/server_abyss.h b/include/xmlrpc-c/server_abyss.h
new file mode 100644 (file)
index 0000000..4882a20
--- /dev/null
@@ -0,0 +1,211 @@
+/* Copyright and license information is at the end of the file */
+
+#ifndef  XMLRPC_SERVER_ABYSS_H_INCLUDED
+#define  XMLRPC_SERVER_ABYSS_H_INCLUDED
+
+#include "xmlrpc-c/abyss.h"
+#include "xmlrpc-c/server.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*=========================================================================
+**  XML-RPC Server (based on Abyss)
+**=========================================================================
+**  A simple XML-RPC server based on the Abyss web server. If errors
+**  occur during server setup, the server will exit. In general, if you
+**  want to use this API, you'll need to be familiar with Abyss.
+**
+**  There are two ways to use Abyss:
+**    1) You can use the handy wrapper functions.
+**    2) You can set up Abyss yourself, and install the appropriate
+**       handlers manually.
+*/
+
+#define XMLRPC_SERVER_ABYSS_NO_FLAGS (0)
+
+
+
+
+/*=========================================================================
+**  Basic Abyss Server Functions
+**=======================================================================*/
+
+typedef void ((*runfirstFn)(void *));
+
+typedef struct {
+    const char *      config_file_name;
+        /* NULL to use preferred proper API-level interface */
+
+    xmlrpc_registry * registryP;
+
+    /* runfirstFn and runfirst_arg are meaningless when 
+       config_file_name is NULL
+    */
+    runfirstFn        runfirst;
+    void *            runfirst_arg;
+
+    unsigned int      port_number;
+    const char *      log_file_name;
+    unsigned int      keepalive_timeout;
+    unsigned int      keepalive_max_conn;
+    unsigned int      timeout;
+    xmlrpc_bool       dont_advertise;
+    xmlrpc_bool       socket_bound;
+    xmlrpc_socket     socket_handle;
+    const char *      uri_path;
+    xmlrpc_bool       chunk_response;
+} xmlrpc_server_abyss_parms;
+
+
+#define XMLRPC_APSIZE(MBRNAME) \
+    XMLRPC_STRUCTSIZE(xmlrpc_server_abyss_parms, MBRNAME)
+
+/* XMLRPC_APSIZE(xyz) is the minimum size a struct xmlrpc_server_abyss_parms
+   must be to include the 'xyz' member.  This is essential to forward and
+   backward compatibility, as new members will be added to the end of the
+   struct in future releases.  This is how the callee knows whether or
+   not the caller is new enough to have supplied a certain parameter.
+*/
+
+void
+xmlrpc_server_abyss(xmlrpc_env *                      const envP,
+                    const xmlrpc_server_abyss_parms * const parms,
+                    unsigned int                      const parm_size);
+
+void
+xmlrpc_server_abyss_set_handlers2(TServer *         const srvP,
+                                  const char *      const filename,
+                                  xmlrpc_registry * const registryP);
+
+void
+xmlrpc_server_abyss_set_handlers(TServer *         const serverP,
+                                 xmlrpc_registry * const registryP);
+
+void
+xmlrpc_server_abyss_set_handler(xmlrpc_env *      const envP,
+                                TServer *         const serverP,
+                                const char *      const filename,
+                                xmlrpc_registry * const registryP);
+
+/*=========================================================================
+**  Handy Abyss Extensions
+**=======================================================================*/
+
+/* These are functions that have nothing to do with Xmlrpc-c, but provide
+   convenient Abyss services beyond those provided by the Abyss library.
+*/
+
+/* Start an Abyss webserver running (previously created and
+** initialized).  Under Unix, this routine will attempt to do a
+** detaching fork, drop root privileges (if any) and create a pid
+** file.  Under Windows, this routine merely starts the server.  This
+** routine never returns.
+**
+** Once you call this routine, it is illegal to modify the server any
+** more, including changing any method registry.
+*/
+void
+xmlrpc_server_abyss_run(void);
+
+/* Same as xmlrpc_server_abyss_run(), except you get to specify a "runfirst"
+** function.  The server runs this just before executing the actual server
+** function, after any daemonizing.  NULL for 'runfirst' means no runfirst
+** function.  'runfirstArg' is the argument the server passes to the runfirst
+** function.
+**/
+void 
+xmlrpc_server_abyss_run_first(void (runfirst(void *)),
+                              void * const runfirstArg);
+
+/*=========================================================================
+**  Method Registry
+**=========================================================================
+   These functions are for the built-in xmlrpc_server_abyss registry.
+   It's usually simpler to skip all this and use the regular method
+   registry services (from xmlrpc_server.h) to build a registry and
+   pass it to xmlrpc_server_abyss.
+*/
+
+/* Call this function to create a new Abyss webserver with the default
+** options and the built-in method registry.  If you've already
+** initialized Abyss using Abyss functions, you can instead call
+** xmlrpc_server_abyss_init_registry() to make it an Xmlrpc-c server.
+** Or use a regular method registry and call
+** xmlrpc_server_abyss_set_handlers().
+**/
+void 
+xmlrpc_server_abyss_init(int          const flags, 
+                         const char * const config_file);
+
+/* This is called automatically by xmlrpc_server_abyss_init. */
+void xmlrpc_server_abyss_init_registry (void);
+
+/* Fetch the internal registry, if you happen to need it. 
+   If you're using this, you really shouldn't be using the built-in
+   registry at all.  It exists today only for backward compatibilty.
+*/
+extern xmlrpc_registry *
+xmlrpc_server_abyss_registry (void);
+
+/* A quick & easy shorthand for adding a method. Depending on
+** how you've configured your copy of Abyss, it's probably not safe to
+** call this method after calling xmlrpc_server_abyss_run. */
+void xmlrpc_server_abyss_add_method (char *method_name,
+                                     xmlrpc_method method,
+                                     void *user_data);
+    
+/* As above, but provide documentation (see xmlrpc_registry_add_method_w_doc
+** for more information). You should really use this one. */
+extern void
+xmlrpc_server_abyss_add_method_w_doc (char *method_name,
+                                      xmlrpc_method method,
+                                      void *user_data,
+                                      char *signature,
+                                      char *help);
+
+/*=========================================================================
+**  Content Handlers
+**=======================================================================*/
+/* Abyss contents handlers xmlrpc_server_abyss_rpc2_handler()
+   and xmlrpc_server_abyss_default_handler() were available in older
+   Xmlrpc-c, but starting with Release 1.01, they are not.  Instead,
+   call xmlrpc_server_abyss_set_handlers() to install them.
+
+   Alternatively, you can write your own handlers that do the same thing.
+   It's not hard, and if you're writing low enough level Abyss code that
+   you can't use xmlrpc_server_abyss_set_handlers(), you probably want to
+   anyway.
+*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#endif
diff --git a/include/xmlrpc-c/server_abyss.hpp b/include/xmlrpc-c/server_abyss.hpp
new file mode 100644 (file)
index 0000000..e420ad3
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef SERVER_ABYSS_HPP_INCLUDED
+#define SERVER_ABYSS_HPP_INCLUDED
+
+#include "xmlrpc-c/base.hpp"
+#include "abyss.h"
+
+namespace xmlrpc_c {
+
+class serverAbyss {
+    
+public:
+    class constrOpt {
+    public:
+        constrOpt();
+
+        constrOpt & registryPtr       (xmlrpc_c::registryPtr      const& arg);
+        constrOpt & registryP         (const xmlrpc_c::registry * const& arg);
+        constrOpt & socketFd          (xmlrpc_socket  const& arg);
+        constrOpt & portNumber        (uint           const& arg);
+        constrOpt & logFileName       (std::string    const& arg);
+        constrOpt & keepaliveTimeout  (uint           const& arg);
+        constrOpt & keepaliveMaxConn  (uint           const& arg);
+        constrOpt & timeout           (uint           const& arg);
+        constrOpt & dontAdvertise     (bool           const& arg);
+        constrOpt & uriPath           (std::string    const& arg);
+        constrOpt & chunkResponse     (bool           const& arg);
+
+        struct value {
+            xmlrpc_c::registryPtr      registryPtr;
+            const xmlrpc_c::registry * registryP;
+            xmlrpc_socket  socketFd;
+            uint           portNumber;
+            std::string    logFileName;
+            uint           keepaliveTimeout;
+            uint           keepaliveMaxConn;
+            uint           timeout;
+            bool           dontAdvertise;
+            std::string    uriPath;
+            bool           chunkResponse;
+        } value;
+        struct {
+            bool registryPtr;
+            bool registryP;
+            bool socketFd;
+            bool portNumber;
+            bool logFileName;
+            bool keepaliveTimeout;
+            bool keepaliveMaxConn;
+            bool timeout;
+            bool dontAdvertise;
+            bool uriPath;
+            bool chunkResponse;
+        } present;
+    };
+
+    serverAbyss(constrOpt const& opt);
+
+    serverAbyss(
+        xmlrpc_c::registry const& registry,
+        unsigned int       const  portNumber = 8080,
+        std::string        const& logFileName = "",
+        unsigned int       const  keepaliveTimeout = 0,
+        unsigned int       const  keepaliveMaxConn = 0,
+        unsigned int       const  timeout = 0,
+        bool               const  dontAdvertise = false,
+        bool               const  socketBound = false,
+        xmlrpc_socket      const  socketFd = 0
+        );
+    ~serverAbyss();
+    
+    void
+    run();
+
+    void
+    runOnce();
+
+    void
+    runConn(int const socketFd);
+    
+private:
+    // The user has the choice of supplying the registry by plain pointer
+    // (and managing the object's existence himself) or by autoObjectPtr
+    // (with automatic management).  'registryPtr' exists here only to
+    // maintain a reference count in the case that the user supplied an
+    // autoObjectPtr.  The object doesn't reference the C++ registry
+    // object except during construction, because the C registry is the
+    // real registry.
+    xmlrpc_c::registryPtr registryPtr;
+
+    TServer cServer;
+
+    void
+    setAdditionalServerParms(constrOpt const& opt);
+
+    void
+    initialize(constrOpt const& opt);
+};
+
+
+void
+server_abyss_set_handlers(TServer *          const  srvP,
+                          xmlrpc_c::registry const& registry,
+                          std::string        const& uriPath = "/RPC2");
+
+void
+server_abyss_set_handlers(TServer *                  const  srvP,
+                          const xmlrpc_c::registry * const  registryP,
+                          std::string                const& uriPath = "/RPC2");
+
+void
+server_abyss_set_handlers(TServer *             const srvP,
+                          xmlrpc_c::registryPtr const registryPtr,
+                          std::string           const& uriPath = "/RPC2");
+
+} // namespace
+
+#endif
diff --git a/include/xmlrpc-c/server_cgi.h b/include/xmlrpc-c/server_cgi.h
new file mode 100644 (file)
index 0000000..ad926aa
--- /dev/null
@@ -0,0 +1,49 @@
+/* Interface header file for libxmlrpc_server_cgi.
+
+   By Bryan Henderson, 05.04.27.  Contributed to the public domain.
+*/
+
+#ifndef  XMLRPC_CGI_H_INCLUDED
+#define  XMLRPC_CGI_H_INCLUDED
+
+#include <xmlrpc-c/server.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+void
+xmlrpc_server_cgi_process_call(xmlrpc_registry * const registryP);
+
+#define XMLRPC_CGI_NO_FLAGS (0)
+
+extern void
+xmlrpc_cgi_init (int flags);
+
+extern xmlrpc_registry *
+xmlrpc_cgi_registry (void);
+
+void
+xmlrpc_cgi_add_method(const char *  const method_name,
+                      xmlrpc_method const method,
+                      void *        const user_data);
+
+void
+xmlrpc_cgi_add_method_w_doc(const char *  const method_name,
+                            xmlrpc_method const method,
+                            void *        const user_data,
+                            const char *  const signature,
+                            const char *  const help);
+extern void
+xmlrpc_cgi_process_call (void);
+
+extern void
+xmlrpc_cgi_cleanup (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/include/xmlrpc-c/server_w32httpsys.h b/include/xmlrpc-c/server_w32httpsys.h
new file mode 100644 (file)
index 0000000..085f6e3
--- /dev/null
@@ -0,0 +1,95 @@
+/* Copyright (C) 2005 by Steven A. Bone, sbone@pobox.com. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+/* COMPILATION NOTE:
+   Note that the Platform SDK headers and
+   link libraries for Windows XP SP2 or newer are required to compile
+   xmlrpc-c for this module.  If you are not using this server, it is 
+   safe to exclude the xmlrpc_server_w32httpsys.c file from the xmlrpc
+   project and these dependencies will not be required.  You can get the 
+   latest platform SDK at 
+   http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+   Be sure after installation to choose the program to "register the PSDK
+   directories with Visual Studio" so the newer headers are found.
+*/
+
+#ifndef  _XMLRPC_SERVER_HTTPSYS_H_
+#define  _XMLRPC_SERVER_HTTPSYS_H_ 1
+
+#include "transport_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*=========================================================================
+**  XML-RPC Server (based on HTTP.SYS)
+**=========================================================================
+**  A simple XML-RPC server based on the "built-in" Windows web server,
+**  HTTP.SYS.  This is provided by Microsoft in Windows XP SP2 and 
+**  Windows Server 2003.  If errors occur during server setup, the server
+**  will exit. In general, if you want to use this API, you do not really
+**  need to be familiar with the HTTP.SYS API.
+*/
+
+typedef void (*authorization_function)(
+                                xmlrpc_env * envP,
+                 char * userid,
+                 char * password);
+
+typedef struct {
+    xmlrpc_registry * registryP;
+       unsigned int      portNum;
+       unsigned int      useSSL;
+       /* useSSL, 0 = no SSL, 1 = use SSL */
+       unsigned int      logLevel;
+       /* logLevel, 0 = none, 1 = file, 2 = file+OutputDebugString() */
+       const char *      logFile;
+       /* logFile, NULL or filename */
+       authorization_function authfn;
+} xmlrpc_server_httpsys_parms;
+
+#define XMLRPC_HSSIZE(MBRNAME) \
+    XMLRPC_STRUCTSIZE(xmlrpc_server_httpsys_parms, MBRNAME)
+
+/* XMLRPC_HSSIZE(xyz) is the minimum size a struct xmlrpc_server_httpsys_parms
+   must be to include the 'xyz' member.  This is essential for forward and
+   backward compatbility, as new members will be added to the end of the
+   struct in future releases.  This is how the callee knows whether or
+   not the caller is new enough to have supplied a certain parameter.
+*/
+
+void
+xmlrpc_server_httpsys(
+       xmlrpc_env *                        const envP,
+    const xmlrpc_server_httpsys_parms * const parmsP,
+    unsigned int                        const parm_size
+       );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/include/xmlrpc-c/sleep_int.h b/include/xmlrpc-c/sleep_int.h
new file mode 100644 (file)
index 0000000..be18e8f
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef SLEEP_INT_H_INCLUDED
+#define SLEEP_INT_H_INCLUDED
+
+void
+xmlrpc_millisecond_sleep(unsigned int const milliseconds);
+
+#endif
diff --git a/include/xmlrpc-c/string_int.h b/include/xmlrpc-c/string_int.h
new file mode 100644 (file)
index 0000000..f1bfb7b
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef XMLRPC_C_STRING_INT_H_INCLUDED
+#define XMLRPC_C_STRING_INT_H_INCLUDED
+
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "xmlrpc-c/base_int.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char * const xmlrpc_strsol;
+
+void
+xmlrpc_vasprintf(const char ** const retvalP,
+                 const char *  const fmt,
+                 va_list             varargs);
+
+void GNU_PRINTF_ATTR(2,3)
+xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...);
+
+void
+xmlrpc_strfree(const char * const string);
+
+static __inline__ bool
+xmlrpc_streq(const char * const a,
+             const char * const b) {
+    return (strcmp(a, b) == 0);
+}
+
+static __inline__ bool
+xmlrpc_strcaseeq(const char * const a,
+                 const char * const b) {
+    return (strcasecmp(a, b) == 0);
+}
+
+static __inline__ bool
+xmlrpc_strneq(const char * const a,
+              const char * const b,
+              size_t       const len) {
+    return (strncmp(a, b, len) == 0);
+}
+
+const char * 
+xmlrpc_makePrintable(const char * const input);
+
+const char *
+xmlrpc_makePrintable_lp(const char * const input,
+                        size_t       const inputLength);
+
+const char *
+xmlrpc_makePrintableChar(char const input);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/xmlrpc-c/timeout.hpp b/include/xmlrpc-c/timeout.hpp
new file mode 100644 (file)
index 0000000..5638300
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef XMLRPC_TIMEOUT_H_INCLUDED
+#define XMLRPC_TIMEOUT_H_INCLUDED
+
+namespace xmlrpc_c {
+
+struct timeout {
+
+    timeout() : finite(false) {}
+
+    timeout(unsigned int const duration) :
+        finite(true), duration(duration) {}
+
+    bool finite;
+    unsigned int duration;
+};
+
+
+} // namespace
+
+#endif
diff --git a/include/xmlrpc-c/transport.h b/include/xmlrpc-c/transport.h
new file mode 100644 (file)
index 0000000..b6ca0d2
--- /dev/null
@@ -0,0 +1,81 @@
+/* Copyright information is at the end of the file */
+#ifndef  XMLRPC_TRANSPORT_H_INCLUDED
+#define  XMLRPC_TRANSPORT_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "xmlrpc-c/base.h"
+
+struct xmlrpc_call_info;
+
+struct xmlrpc_client_transport;
+
+/*=========================================================================
+**  Transport function type declarations.
+**=========================================================================
+*/
+typedef void (*xmlrpc_transport_setup)(xmlrpc_env * const envP);
+
+typedef void (*xmlrpc_transport_teardown)(void);
+
+typedef void (*xmlrpc_transport_create)(
+    xmlrpc_env *                      const envP,
+    int                               const flags,
+    const char *                      const appname,
+    const char *                      const appversion,
+    const struct xmlrpc_xportparms *  const transportparmsP,
+    size_t                            const transportparm_size,
+    struct xmlrpc_client_transport ** const handlePP);
+    
+typedef void (*xmlrpc_transport_destroy)(
+    struct xmlrpc_client_transport * const clientTransportP);
+
+typedef void (*xmlrpc_transport_asynch_complete)(
+    struct xmlrpc_call_info * const callInfoP,
+    xmlrpc_mem_block *        const responseXmlP,
+    xmlrpc_env                const env);
+
+typedef void (*xmlrpc_transport_send_request)(
+    xmlrpc_env *                     const envP, 
+    struct xmlrpc_client_transport * const clientTransportP,
+    const xmlrpc_server_info *       const serverP,
+    xmlrpc_mem_block *               const xmlP,
+    xmlrpc_transport_asynch_complete       complete,
+    struct xmlrpc_call_info *        const callInfoP);
+
+typedef void (*xmlrpc_transport_call)(
+    xmlrpc_env *                     const envP,
+    struct xmlrpc_client_transport * const clientTransportP,
+    const xmlrpc_server_info *       const serverP,
+    xmlrpc_mem_block *               const xmlP,
+    xmlrpc_mem_block **              const responsePP);
+
+typedef enum {timeout_no, timeout_yes} xmlrpc_timeoutType;
+
+typedef unsigned long xmlrpc_timeout;
+    /* A timeout in milliseconds. */
+
+typedef void (*xmlrpc_transport_finish_asynch)(
+    struct xmlrpc_client_transport * const clientTransportP,
+    xmlrpc_timeoutType               const timeoutType,
+    xmlrpc_timeout                   const timeout);
+
+
+struct xmlrpc_client_transport_ops {
+
+    xmlrpc_transport_setup         setup_global_const;
+    xmlrpc_transport_teardown      teardown_global_const;
+    xmlrpc_transport_create        create;
+    xmlrpc_transport_destroy       destroy;
+    xmlrpc_transport_send_request  send_request;
+    xmlrpc_transport_call          call;
+    xmlrpc_transport_finish_asynch finish_asynch;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/xmlrpc-c/util.h b/include/xmlrpc-c/util.h
new file mode 100644 (file)
index 0000000..541e385
--- /dev/null
@@ -0,0 +1,313 @@
+/*=============================================================================
+                                 xmlrpc-c/util.h
+===============================================================================
+
+  This is the interface to the libxmlrpc_util library, which contains
+  utility routines that have nothing to do with XML-RPC.  The library
+  exists because other Xmlrpc-c libraries use the utilities.
+
+  By Bryan Henderson, San Jose, CA 05.09.21.
+
+  Contributed to the public domain by its author.
+=============================================================================*/
+
+#ifndef XMLRPC_C_UTIL_H_INCLUDED
+#define XMLRPC_C_UTIL_H_INCLUDED
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type
+   calls to be sure the arguments match the format string, thus preventing
+   runtime segmentation faults and incorrect messages.
+*/
+#ifdef __GNUC__
+#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
+#else
+#define GNU_PRINTF_ATTR(a,b)
+#endif
+
+
+/*=========================================================================
+**  C struct size computations
+**=======================================================================*/
+
+/* Use XMLRPC_STRUCT_MEMBER_SIZE() to determine how big a structure is
+   up to and including a specified member.  E.g. if you have
+   struct mystruct {int red; int green; int blue};, then
+   XMLRPC_STRUCT_MEMBER_SIZE(mystruct, green) is (8).
+*/
+
+#define _XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) \
+  ((unsigned long)(char*)&((TYPE *)0)->MBRNAME)
+#define _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME) \
+  sizeof(((TYPE *)0)->MBRNAME)
+#define XMLRPC_STRUCTSIZE(TYPE, MBRNAME) \
+  (_XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) + \
+  _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME))
+
+/*=========================================================================
+**  Assertions and Debugging
+**=========================================================================
+**  Note that an assertion is _not_ a directive to check a condition and
+**  crash if it isn't true.  It is an assertion that the condition _is_
+**  true.  This assertion helps people to read the code.  The program
+**  may also check the assertion as it runs, and if it conflicts with reality,
+**  recognize that the program is incorrect and abort it.  In practice,
+**  it does this checking when the program was compiled without the NDEBUG
+**  macro defined.
+*/
+
+#ifndef NDEBUG
+
+#define XMLRPC_ASSERT(cond) \
+    do \
+        if (!(cond)) \
+            xmlrpc_assertion_failed(__FILE__, __LINE__); \
+    while (0)
+
+#else
+#define XMLRPC_ASSERT(cond) while (0) {}
+#endif
+
+void
+xmlrpc_assertion_failed(const char * const fileName,
+                        int          const lineNumber);
+
+/* Validate a pointer. */
+#define XMLRPC_ASSERT_PTR_OK(ptr) \
+    XMLRPC_ASSERT((ptr) != NULL)
+
+/* We only call this if something truly drastic happens. */
+#define XMLRPC_FATAL_ERROR(msg) xmlrpc_fatal_error(__FILE__, __LINE__, (msg))
+
+extern void xmlrpc_fatal_error (char* file, int line, char* msg);
+
+
+/*=========================================================================
+**  xmlrpc_env
+**=========================================================================
+**  XML-RPC represents runtime errors as <fault> elements. These contain
+**  <faultCode> and <faultString> elements.
+**
+**  Since we need as much thread-safety as possible, we borrow an idea from
+**  CORBA--we store exception information in an "environment" object.
+**  You'll pass this to many different functions, and it will get filled
+**  out appropriately.
+**
+**  For example:
+**
+**    xmlrpc_env env;
+**
+**    xmlrpc_env_init(&env);
+**
+**    xmlrpc_do_something(&env);
+**    if (env.fault_occurred)
+**        report_error_appropriately();
+**
+**    xmlrpc_env_clean(&env);
+*/
+
+#define XMLRPC_INTERNAL_ERROR               (-500)
+#define XMLRPC_TYPE_ERROR                   (-501)
+#define XMLRPC_INDEX_ERROR                  (-502)
+#define XMLRPC_PARSE_ERROR                  (-503)
+#define XMLRPC_NETWORK_ERROR                (-504)
+#define XMLRPC_TIMEOUT_ERROR                (-505)
+#define XMLRPC_NO_SUCH_METHOD_ERROR         (-506)
+#define XMLRPC_REQUEST_REFUSED_ERROR        (-507)
+#define XMLRPC_INTROSPECTION_DISABLED_ERROR (-508)
+#define XMLRPC_LIMIT_EXCEEDED_ERROR         (-509)
+#define XMLRPC_INVALID_UTF8_ERROR           (-510)
+
+typedef struct _xmlrpc_env {
+    int    fault_occurred;
+    int    fault_code;
+    char * fault_string;
+} xmlrpc_env;
+
+/* Initialize and destroy the contents of the provided xmlrpc_env object.
+** These functions will never fail. */
+void xmlrpc_env_init (xmlrpc_env* env);
+void xmlrpc_env_clean (xmlrpc_env* env);
+
+/* Fill out an xmlrpc_fault with the specified values, and set the
+** fault_occurred flag. This function will make a private copy of 'string',
+** so you retain responsibility for your copy. */
+void 
+xmlrpc_env_set_fault(xmlrpc_env * const env, 
+                     int          const faultCode, 
+                     const char * const faultDescription);
+
+/* The same as the above, but using a printf-style format string. */
+void 
+xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP, 
+                               int          const code,
+                               const char * const format, 
+                               ...) GNU_PRINTF_ATTR(3,4);
+
+/* This one infers XMLRPC_INTERNAL_ERROR and has a shorter name.
+   So a call takes up less source code space.
+*/
+void
+xmlrpc_faultf(xmlrpc_env * const envP,
+              const char * const format,
+              ...) GNU_PRINTF_ATTR(2,3);
+
+/* A simple debugging assertion. */
+#define XMLRPC_ASSERT_ENV_OK(envP) \
+    XMLRPC_ASSERT((envP) != NULL && \
+    (envP->fault_string == NULL) && \
+    !(envP)->fault_occurred)
+
+/* This version must *not* interpret 'str' as a format string, to avoid
+** several evil attacks. */
+#define XMLRPC_FAIL(env,code,str) \
+    do { xmlrpc_env_set_fault((env),(code),(str)); goto cleanup; } while (0)
+
+#define XMLRPC_FAIL1(env,code,str,arg1) \
+    do { \
+        xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1)); \
+        goto cleanup; \
+    } while (0)
+
+#define XMLRPC_FAIL2(env,code,str,arg1,arg2) \
+    do { \
+        xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1),(arg2)); \
+        goto cleanup; \
+    } while (0)
+
+#define XMLRPC_FAIL3(env,code,str,arg1,arg2,arg3) \
+    do { \
+        xmlrpc_env_set_fault_formatted((env),(code), \
+                                       (str),(arg1),(arg2),(arg3)); \
+        goto cleanup; \
+    } while (0)
+
+#define XMLRPC_FAIL_IF_NULL(ptr,env,code,str) \
+    do { \
+        if ((ptr) == NULL) \
+            XMLRPC_FAIL((env),(code),(str)); \
+    } while (0)
+
+#define XMLRPC_FAIL_IF_FAULT(env) \
+    do { if ((env)->fault_occurred) goto cleanup; } while (0)
+
+
+/*=========================================================================
+**  Resource Limits
+**=========================================================================
+**  To discourage denial-of-service attacks, we provide several adjustable
+**  resource limits. These functions are *not* re-entrant.
+*/
+
+/* Limit IDs. There will be more of these as time goes on. */
+#define XMLRPC_NESTING_LIMIT_ID   (0)
+#define XMLRPC_XML_SIZE_LIMIT_ID  (1)
+#define XMLRPC_LAST_LIMIT_ID      (XMLRPC_XML_SIZE_LIMIT_ID)
+
+/* By default, deserialized data may be no more than 64 levels deep. */
+#define XMLRPC_NESTING_LIMIT_DEFAULT  (64)
+
+/* By default, XML data from the network may be no larger than 512K.
+** Some client and server modules may fail to enforce this properly. */
+#define XMLRPC_XML_SIZE_LIMIT_DEFAULT (512*1024)
+
+/* Set a specific limit to the specified value. */
+extern void xmlrpc_limit_set (int limit_id, size_t value);
+
+/* Get the value of a specified limit. */
+extern size_t xmlrpc_limit_get (int limit_id);
+
+
+/*=========================================================================
+**  xmlrpc_mem_block
+**=========================================================================
+**  A resizable chunk of memory. This is mostly used internally, but it is
+**  also used by the public API in a few places.
+**  The struct fields are private!
+*/
+
+typedef struct _xmlrpc_mem_block {
+    size_t _size;
+    size_t _allocated;
+    void*  _block;
+} xmlrpc_mem_block;
+
+/* Allocate a new xmlrpc_mem_block. */
+xmlrpc_mem_block* xmlrpc_mem_block_new (xmlrpc_env* env, size_t size);
+
+/* Destroy an existing xmlrpc_mem_block, and everything it contains. */
+void xmlrpc_mem_block_free (xmlrpc_mem_block* block);
+
+/* Initialize the contents of the provided xmlrpc_mem_block. */
+void xmlrpc_mem_block_init
+    (xmlrpc_env* env, xmlrpc_mem_block* block, size_t size);
+
+/* Deallocate the contents of the provided xmlrpc_mem_block, but not the
+** block itself. */
+void xmlrpc_mem_block_clean (xmlrpc_mem_block* block);
+
+/* Get the size and contents of the xmlrpc_mem_block. */
+size_t 
+xmlrpc_mem_block_size(const xmlrpc_mem_block * const block);
+
+void * 
+xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block);
+
+/* Resize an xmlrpc_mem_block, preserving as much of the contents as
+** possible. */
+void xmlrpc_mem_block_resize
+    (xmlrpc_env* env, xmlrpc_mem_block* block, size_t size);
+
+/* Append data to an existing xmlrpc_mem_block. */
+void xmlrpc_mem_block_append
+    (xmlrpc_env* env, xmlrpc_mem_block* block, const void *data, size_t len);
+
+#define XMLRPC_MEMBLOCK_NEW(type,env,size) \
+    xmlrpc_mem_block_new((env), sizeof(type) * (size))
+#define XMLRPC_MEMBLOCK_FREE(type,block) \
+    xmlrpc_mem_block_free(block)
+#define XMLRPC_MEMBLOCK_INIT(type,env,block,size) \
+    xmlrpc_mem_block_init((env), (block), sizeof(type) * (size))
+#define XMLRPC_MEMBLOCK_CLEAN(type,block) \
+    xmlrpc_mem_block_clean(block)
+#define XMLRPC_MEMBLOCK_SIZE(type,block) \
+    (xmlrpc_mem_block_size(block) / sizeof(type))
+#define XMLRPC_MEMBLOCK_CONTENTS(type,block) \
+    ((type*) xmlrpc_mem_block_contents(block))
+#define XMLRPC_MEMBLOCK_RESIZE(type,env,block,size) \
+    xmlrpc_mem_block_resize(env, block, sizeof(type) * (size))
+#define XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size) \
+    xmlrpc_mem_block_append(env, block, data, sizeof(type) * (size))
+
+/* Here are some backward compatibility definitions.  These longer names
+   used to be the only ones and typed memory blocks were considered
+   special.
+*/
+#define XMLRPC_TYPED_MEM_BLOCK_NEW(type,env,size) \
+    XMLRPC_MEMBLOCK_NEW(type,env,size)
+#define XMLRPC_TYPED_MEM_BLOCK_FREE(type,block) \
+    XMLRPC_MEMBLOCK_FREE(type,block)
+#define XMLRPC_TYPED_MEM_BLOCK_INIT(type,env,block,size) \
+    XMLRPC_MEMBLOCK_INIT(type,env,block,size)
+#define XMLRPC_TYPED_MEM_BLOCK_CLEAN(type,block) \
+    XMLRPC_MEMBLOCK_CLEAN(type,block)
+#define XMLRPC_TYPED_MEM_BLOCK_SIZE(type,block) \
+    XMLRPC_MEMBLOCK_SIZE(type,block)
+#define XMLRPC_TYPED_MEM_BLOCK_CONTENTS(type,block) \
+    XMLRPC_MEMBLOCK_CONTENTS(type,block)
+#define XMLRPC_TYPED_MEM_BLOCK_RESIZE(type,env,block,size) \
+    XMLRPC_MEMBLOCK_RESIZE(type,env,block,size)
+#define XMLRPC_TYPED_MEM_BLOCK_APPEND(type,env,block,data,size) \
+    XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/xmlrpc-c/util_int.h b/include/xmlrpc-c/util_int.h
new file mode 100644 (file)
index 0000000..4ac3e14
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef XMLRPC_C_UTIL_INT_H_INCLUDED
+#define XMLRPC_C_UTIL_INT_H_INCLUDED
+
+#include "util.h"
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+/* When we deallocate a pointer in a struct, we often replace it with
+** this and throw in a few assertions here and there. */
+#define XMLRPC_BAD_POINTER ((void*) 0xDEADBEEF)
+
+#endif
diff --git a/include/xmlrpc-c/xml.hpp b/include/xmlrpc-c/xml.hpp
new file mode 100644 (file)
index 0000000..cb24f0f
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef XML_HPP_INCLUDED
+#define XML_HPP_INCLUDED
+
+#include <string>
+#include <xmlrpc-c/base.hpp>
+
+namespace xmlrpc_c {
+namespace xml {
+
+void
+generateCall(std::string         const& methodName,
+             xmlrpc_c::paramList const& paramList,
+             std::string *       const  callXmlP);
+    
+void
+parseSuccessfulResponse(std::string       const& responseXml,
+                        xmlrpc_c::value * const  resultP);
+
+void
+parseResponse(std::string            const& responseXml,
+              xmlrpc_c::rpcOutcome * const  outcomeP);
+
+
+void
+trace(std::string const& label,
+      std::string const& xml);
+
+
+}} // namespace
+#endif
diff --git a/include/xmlrpc-c/xmlparser.h b/include/xmlrpc-c/xmlparser.h
new file mode 100644 (file)
index 0000000..ad1361f
--- /dev/null
@@ -0,0 +1,97 @@
+/* Copyright and license information is at the end of the file */
+
+#ifndef XMLRPC_XMLPARSER_H_INCLUDED
+#define XMLRPC_XMLPARSER_H_INCLUDED
+
+/*=========================================================================
+**  Abstract XML Parser Interface
+**=========================================================================
+**  This file provides an abstract interface to the XML parser. For now,
+**  this interface is implemented by expat, but feel free to change it
+**  if necessary.
+*/
+
+
+/*=========================================================================
+**  xml_element
+**=========================================================================
+**  This data structure represents an XML element. We provide no more API
+**  than we'll need in xmlrpc_parse.c.
+**
+**  The pointers returned by the various accessor methods belong to the
+**  xml_element structure. Do not free them, and do not use them after
+**  the xml_element has been destroyed.
+*/
+
+/* You'll need to finish defining struct _xml_element elsewhere. */
+typedef struct _xml_element xml_element;
+
+/* Destroy an xml_element. */
+void xml_element_free (xml_element *elem);
+
+/* Return a pointer to the element's name. Do not free this pointer!
+** This pointer should point to standard ASCII or UTF-8 data. */
+const char *
+xml_element_name(const xml_element * const elemP);
+
+/* Return the xml_element's CDATA. Do not free this pointer!
+** This pointer should point to standard ASCII or UTF-8 data.
+** The implementation is allowed to concatenate all the CDATA in the
+** element regardless of child elements. Alternatively, if there are
+** any child elements, the implementation is allowed to dispose
+** of whitespace characters.
+** The value returned by xml_element_cdata should be '\0'-terminated
+** (although it may contain other '\0' characters internally).
+** xml_element_cdata_size should not include the final '\0'. */
+size_t xml_element_cdata_size (xml_element *elem);
+char *xml_element_cdata (xml_element *elem);
+
+/* Return the xml_element's child elements. Do not free this pointer! */
+size_t
+xml_element_children_size(const xml_element * const elemP);
+
+xml_element **
+xml_element_children(const xml_element * const elemP);
+
+
+/*=========================================================================
+**  xml_parse
+**=========================================================================
+**  Parse a chunk of XML data and return the top-level element. If this
+**  routine fails, it will return NULL and set up the env appropriately.
+**  You are responsible for calling xml_element_free on the returned pointer.
+*/
+
+void
+xml_parse(xmlrpc_env *   const envP,
+          const char *   const xmlData,
+          size_t         const xmlDataLen,
+          xml_element ** const resultPP);
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#endif
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..e9de238
--- /dev/null
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+               chmodcmd=""
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644 (file)
index 0000000..3826372
--- /dev/null
@@ -0,0 +1,52 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/..
+endif
+SUBDIR = lib
+
+include $(SRCDIR)/Makefile.config
+
+# Build up SUBDIRS:
+SUBDIRS = 
+SUBDIRS += util libutil
+ifeq ($(ENABLE_ABYSS_SERVER),yes)
+  SUBDIRS += abyss
+endif
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+  SUBDIRS += wininet_transport
+endif
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+  SUBDIRS += curl_transport
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+  SUBDIRS += libwww_transport
+endif
+ifneq ($(ENABLE_LIBXML2_BACKEND),yes)
+  SUBDIRS += expat
+endif
+
+default: all
+
+.PHONY: all clean distclean tags distdir intall check dep
+
+all: $(SUBDIRS:%=%/all)
+
+clean: $(SUBDIRS:%=%/clean) clean-common
+
+distclean: $(SUBDIRS:%=%/distclean) distclean-common
+
+tags: $(SUBDIRS:%=%/tags) TAGS
+
+DISTFILES = 
+
+distdir: distdir-common
+
+install: $(SUBDIRS:%=%/install)
+
+check:
+
+dep: $(SUBDIRS:%=%/dep)
+
+include $(SRCDIR)/Makefile.common
+
+
+
diff --git a/lib/Makefile.depend b/lib/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/abyss/Makefile b/lib/abyss/Makefile
new file mode 100644 (file)
index 0000000..b0c4325
--- /dev/null
@@ -0,0 +1,38 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+SUBDIR = lib/abyss
+
+include $(SRCDIR)/Makefile.config
+
+SUBDIRS = src
+
+default: all
+
+.PHONY: all
+all: $(SUBDIRS:%=%/all)
+
+.PHONY: clean
+clean: $(SUBDIRS:%=%/clean) clean-common
+
+.PHONY: distclean
+distclean: $(SUBDIRS:%=%/distclean) distclean-common
+
+.PHONY: tags
+tags: $(SUBDIRS:%=%/tags) TAGS
+
+DISTFILES = 
+
+.PHONY: distdir
+distdir: distdir-common
+
+.PHONY: install
+install: $(SUBDIRS:%=%/install)
+
+.PHONY: dep
+dep: $(SUBDIRS:%=%/dep)
+
+include $(SRCDIR)/Makefile.common
+
+
+
diff --git a/lib/abyss/Makefile.depend b/lib/abyss/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/abyss/README b/lib/abyss/README
new file mode 100644 (file)
index 0000000..b1d6c80
--- /dev/null
@@ -0,0 +1,23 @@
+This directory contains the Abyss HTTP server component of XML-RPC For C/C++
+(Xmlrpc-c).
+
+This was derived from the independently developed and distributed
+Abyss web server package in 2001.  Since that time, work has stopped
+on package except for a non-free derivative of it that the original
+author has done.  He uses the Abyss name for that.
+
+So this is now strictly a piece of Xmlrpc-c.  Some day, we should change
+the name to avoid confusion with the old code on which it was based and
+the current non-free version.
+
+But for Xmlrpc-c, we don't want to enhance this much.  That would
+duplicate the vast amount of work that has gone into other HTTP (web)
+servers such as Apache.  If someone needs fancy HTTP service for
+XML-RPC, he should use Apache.  One can use Apache with Xmlrpc-c
+either by using an Apache request handler plugin or by using a CGI
+script.  Abyss is just for very simple servers, where the complexity
+of using (or even acquiring) Apache would not be warranted.
+
+
+Everything besides what's in the src/ directory is just historical --
+it comes from the original Abyss in 2001.
diff --git a/lib/abyss/change.log b/lib/abyss/change.log
new file mode 100644 (file)
index 0000000..2d32d1a
--- /dev/null
@@ -0,0 +1,34 @@
+                     Change log for the ABYSS Web Server
+                     -----------------------------------
+
+Version 0.3 (March 23,2000):
+----------------------------
+* Handles conditional GET requests (by date)
+* Conforms to all the MUSTs of the RFC2616 (newer version of the HTTP/1.1 protocol draft)
+* New configuration options (such as pidfile for UNIX systems...)
+* Handles HEAD and OPTIONS methods
+* Many bug fixes
+* Tested on Sun-OS 5.7
+* Second public release
+
+Version 0.2 beta (February 7,2000):
+-----------------------------------
+* Handles GET on static files
+* Handles correctly range requests
+* Conforms to 80% of the MUSTs of the RFC2068 (HTTP/1.1 protocol draft)
+* Improved code portability (Win32 and UNIX platforms)
+* Tested on Linux 2.2 and Win95/98
+* First public release
+
+Version 0.1 (January 2000):
+---------------------------
+* Completely rewritten in C
+* Speed improvement
+* New memory allocation scheme (using pools)
+* Never released
+
+Version 0.0 (January 2000):
+---------------------------
+* Initial version
+* Written in C++
+* Never released
\ No newline at end of file
diff --git a/lib/abyss/conf/abyss.conf b/lib/abyss/conf/abyss.conf
new file mode 100644 (file)
index 0000000..c74c758
--- /dev/null
@@ -0,0 +1,56 @@
+# ABYSS Web Server configuration file
+# (C) Moez Mahfoudh - 2000
+
+# Cases in option names are ignored, 
+# that means that PORT=port=PoRT=..
+
+# When writing paths, do not worry about / or \ use.
+# ABYSS will substitute / with \ on Win32 systems.
+
+# Options which are system specific (such as User) are
+# ignored on systems which do not handle them.
+
+# The Port option tells the server on which TCP port to listen.
+# default is 80
+Port 8000
+
+# The name or #number of the user to run the server as if it is 
+# launched as root (UNIX specific)
+User nobody
+
+# The Server Root (UNIX systems style)
+ServerRoot /home/mahfoudh/abyss
+
+# The Server Root (Win32 systems style)
+# ServerRoot c:\abyss
+
+# The Path option specifies the web files path.
+Path htdocs
+
+# The Default option contains the name of the files the server should
+# look for when only a path is given (e.g. http://myserver/info/).
+Default index.html index.htm INDEX.HTM INDEX.HTML
+
+# The KeepAlive option is used to set the maximum number of requests
+# served using the same persistent connection.
+KeepAlive 10
+
+# The TimeOut option tells the server how much seconds to wait for
+# an idle connection before closing it.
+TimeOut 10
+
+# The MimeTypes option specifies the location of the file
+# containing the mapping of MIME types and files extensions
+MimeTypes conf/mime.types
+
+# The path of the log file
+LogFile log/access.log
+
+# The file where the pid of the server is logged (UNIX specific)
+PidFile log/abyss.pid
+
+# If AdvertiseServer if set to no, then no server field would be
+# appended to the responses. This is the way to make the server
+# identity unknown to some malicious people which can profit from
+# well known security holes in the software to crash it.
+AdvertiseServer yes
diff --git a/lib/abyss/conf/mime.types b/lib/abyss/conf/mime.types
new file mode 100644 (file)
index 0000000..d53db0f
--- /dev/null
@@ -0,0 +1,276 @@
+# This is a comment. I love comments.
+
+# This file controls what Internet media types are sent to the client for
+# given file extension(s).  Sending the correct media type to the client
+# is important so they know how to handle the content of the file.
+# Extra types can either be added here or by using an AddType directive
+# in your config files. For more information about Internet media types,
+# please read RFC 2045, 2046, 2047, 2048, and 2077.  The Internet media type
+# registry is at <ftp://ftp.iana.org/in-notes/iana/assignments/media-types/>.
+
+# MIME type                    Extension
+application/EDI-Consent
+application/EDI-X12
+application/EDIFACT
+application/activemessage
+application/andrew-inset       ez
+application/applefile
+application/atomicmail
+application/cals-1840
+application/commonground
+application/cybercash
+application/dca-rft
+application/dec-dx
+application/eshop
+application/hyperstudio
+application/iges
+application/mac-binhex40       hqx
+application/mac-compactpro     cpt
+application/macwriteii
+application/marc
+application/mathematica
+application/msword             doc
+application/news-message-id
+application/news-transmission
+application/octet-stream       bin dms lha lzh exe class
+application/oda                        oda
+application/pdf                        pdf
+application/pgp-encrypted
+application/pgp-keys
+application/pgp-signature
+application/pkcs10
+application/pkcs7-mime
+application/pkcs7-signature
+application/postscript         ai eps ps
+application/prs.alvestrand.titrax-sheet
+application/prs.cww
+application/prs.nprend
+application/remote-printing
+application/riscos
+application/rtf                        rtf
+application/set-payment
+application/set-payment-initiation
+application/set-registration
+application/set-registration-initiation
+application/sgml
+application/sgml-open-catalog
+application/slate
+application/smil               smi smil
+application/vemmi
+application/vnd.3M.Post-it-Notes
+application/vnd.FloGraphIt
+application/vnd.acucobol
+application/vnd.anser-web-certificate-issue-initiation
+application/vnd.anser-web-funds-transfer-initiation
+application/vnd.audiograph
+application/vnd.businessobjects
+application/vnd.claymore
+application/vnd.comsocaller
+application/vnd.dna
+application/vnd.dxr
+application/vnd.ecdis-update
+application/vnd.ecowin.chart
+application/vnd.ecowin.filerequest
+application/vnd.ecowin.fileupdate
+application/vnd.ecowin.series
+application/vnd.ecowin.seriesrequest
+application/vnd.ecowin.seriesupdate
+application/vnd.enliven
+application/vnd.epson.salt
+application/vnd.fdf
+application/vnd.ffsns
+application/vnd.framemaker
+application/vnd.fujitsu.oasys
+application/vnd.fujitsu.oasys2
+application/vnd.fujitsu.oasys3
+application/vnd.fujitsu.oasysgp
+application/vnd.fujitsu.oasysprs
+application/vnd.fujixerox.docuworks
+application/vnd.hp-HPGL
+application/vnd.hp-PCL
+application/vnd.hp-PCLXL
+application/vnd.hp-hps
+application/vnd.ibm.MiniPay
+application/vnd.ibm.modcap
+application/vnd.intercon.formnet
+application/vnd.intertrust.digibox
+application/vnd.intertrust.nncp
+application/vnd.is-xpr
+application/vnd.japannet-directory-service
+application/vnd.japannet-jpnstore-wakeup
+application/vnd.japannet-payment-wakeup
+application/vnd.japannet-registration
+application/vnd.japannet-registration-wakeup
+application/vnd.japannet-setstore-wakeup
+application/vnd.japannet-verification
+application/vnd.japannet-verification-wakeup
+application/vnd.koan
+application/vnd.lotus-1-2-3
+application/vnd.lotus-approach
+application/vnd.lotus-freelance
+application/vnd.lotus-organizer
+application/vnd.lotus-screencam
+application/vnd.lotus-wordpro
+application/vnd.meridian-slingshot
+application/vnd.mif            mif
+application/vnd.minisoft-hp3000-save
+application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.ms-artgalry
+application/vnd.ms-asf
+application/vnd.ms-excel       xls
+application/vnd.ms-powerpoint  ppt
+application/vnd.ms-project
+application/vnd.ms-tnef
+application/vnd.ms-works
+application/vnd.music-niff
+application/vnd.musician
+application/vnd.netfpx
+application/vnd.noblenet-directory
+application/vnd.noblenet-sealer
+application/vnd.noblenet-web
+application/vnd.novadigm.EDM
+application/vnd.novadigm.EDX
+application/vnd.novadigm.EXT
+application/vnd.osa.netdeploy
+application/vnd.powerbuilder6
+application/vnd.powerbuilder6-s
+application/vnd.rapid
+application/vnd.seemail
+application/vnd.shana.informed.formtemplate
+application/vnd.shana.informed.interchange
+application/vnd.shana.informed.package
+application/vnd.street-stream
+application/vnd.svd
+application/vnd.swiftview-ics
+application/vnd.truedoc
+application/vnd.visio
+application/vnd.webturbo
+application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf
+application/vnd.xara
+application/vnd.yellowriver-custom-menu
+application/wita
+application/wordperfect5.1
+application/x-bcpio            bcpio
+application/x-cdlink           vcd
+application/x-chess-pgn                pgn
+application/x-compress
+application/x-cpio             cpio
+application/x-csh              csh
+application/x-director         dcr dir dxr
+application/x-dvi              dvi
+application/x-futuresplash     spl
+application/x-gtar             gtar
+application/x-gzip
+application/x-hdf              hdf
+application/x-javascript       js
+application/x-koan             skp skd skt skm
+application/x-latex            latex
+application/x-netcdf           nc cdf
+application/x-sh               sh
+application/x-shar             shar
+application/x-shockwave-flash  swf
+application/x-stuffit          sit
+application/x-sv4cpio          sv4cpio
+application/x-sv4crc           sv4crc
+application/x-tar              tar
+application/x-tcl              tcl
+application/x-tex              tex
+application/x-texinfo          texinfo texi
+application/x-troff            t tr roff
+application/x-troff-man                man
+application/x-troff-me         me
+application/x-troff-ms         ms
+application/x-ustar            ustar
+application/x-wais-source      src
+application/x400-bp
+application/xml
+application/zip                        zip
+audio/32kadpcm
+audio/basic                    au snd
+audio/midi                     mid midi kar
+audio/mpeg                     mpga mp2 mp3
+audio/vnd.qcelp
+audio/x-aiff                   aif aiff aifc
+audio/x-pn-realaudio           ram rm
+audio/x-pn-realaudio-plugin    rpm
+audio/x-realaudio              ra
+audio/x-wav                    wav
+chemical/x-pdb                 pdb xyz
+image/bmp                      bmp
+image/cgm
+image/g3fax
+image/gif                      gif
+image/ief                      ief
+image/jpeg                     jpeg jpg jpe
+image/naplps
+image/png                      png
+image/prs.btif
+image/tiff                     tiff tif
+image/vnd.dwg
+image/vnd.dxf
+image/vnd.fpx
+image/vnd.net-fpx
+image/vnd.svf
+image/vnd.xiff
+image/x-cmu-raster             ras
+image/x-portable-anymap                pnm
+image/x-portable-bitmap                pbm
+image/x-portable-graymap       pgm
+image/x-portable-pixmap                ppm
+image/x-rgb                    rgb
+image/x-xbitmap                        xbm
+image/x-xpixmap                        xpm
+image/x-xwindowdump            xwd
+message/delivery-status
+message/disposition-notification
+message/external-body
+message/http
+message/news
+message/partial
+message/rfc822
+model/iges                     igs iges
+model/mesh                     msh mesh silo
+model/vnd.dwf
+model/vrml                     wrl vrml
+multipart/alternative
+multipart/appledouble
+multipart/byteranges
+multipart/digest
+multipart/encrypted
+multipart/form-data
+multipart/header-set
+multipart/mixed
+multipart/parallel
+multipart/related
+multipart/report
+multipart/signed
+multipart/voice-message
+text/css                       css
+text/directory
+text/enriched
+text/html                      html htm
+text/plain                     asc txt
+text/prs.lines.tag
+text/rfc822-headers
+text/richtext                  rtx
+text/rtf                       rtf
+text/sgml                      sgml sgm
+text/tab-separated-values      tsv
+text/uri-list
+text/vnd.abc
+text/vnd.flatland.3dml
+text/vnd.fmi.flexstor
+text/vnd.in3d.3dml
+text/vnd.in3d.spot
+text/vnd.latex-z
+text/x-setext                  etx
+text/xml                       xml
+video/mpeg                     mpeg mpg mpe
+video/quicktime                        qt mov
+video/vnd.motorola.video
+video/vnd.motorola.videop
+video/vnd.vivo
+video/x-msvideo                        avi
+video/x-sgi-movie              movie
+x-conference/x-cooltalk                ice
diff --git a/lib/abyss/htdocs/index.htm b/lib/abyss/htdocs/index.htm
new file mode 100644 (file)
index 0000000..f0369a5
--- /dev/null
@@ -0,0 +1,21 @@
+<HTML>
+<HEAD>
+<TITLE>ABYSS is working !!!</TITLE>
+</HEAD>
+<BODY bgColor=#80a0f0 text=#000000>
+<H1 align=center>Congratulations, ABYSS is working !!!</H1>
+<BR>
+<P>
+<B>ABYSS</B> Web Server is working correctly on your system. You should now change this
+page with yours.
+<BR>
+Please include in your web pages (at least the first), the <b><i>'Powered by ABYSS'</i></b>
+banner to promote the use of <B>ABYSS</B>.
+</P>
+<hr>
+<P>
+<CENTER><FONT size=-1>
+Copyright Â© 2000 <A href="mailto:mmoez@bigfoot.com">Moez Mahfoudh</A>. All rights reserved.
+</FONT>
+<BR><BR><A href="http://abyss.linuxave.net/"><IMG border=0 src="pwrabyss.gif"></A></center></P>
+</BODY></HTML>
diff --git a/lib/abyss/htdocs/pwrabyss.gif b/lib/abyss/htdocs/pwrabyss.gif
new file mode 100644 (file)
index 0000000..9a4a3a3
Binary files /dev/null and b/lib/abyss/htdocs/pwrabyss.gif differ
diff --git a/lib/abyss/license.txt b/lib/abyss/license.txt
new file mode 100644 (file)
index 0000000..1ee9c9f
--- /dev/null
@@ -0,0 +1,27 @@
+                         ABYSS Web Server License
+                         ------------------------
+
+Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission. 
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/lib/abyss/patch_notes.txt b/lib/abyss/patch_notes.txt
new file mode 100644 (file)
index 0000000..8ca4f77
--- /dev/null
@@ -0,0 +1,114 @@
+Notes about the Abyss Patch -- By: Rosimildo da Silva, Jan 31, 2001.
+-------------------------------------------------------------------
+
+This file contains some notes about the changes made to the
+Abyss source tree. The changes were required to fix a few 
+bugs, and port the base code to compile under CygWin,
+and Borland C++ free compiler. The free compiler for 
+Win32 from Borland can be downloaded from here:
+
+  http://www.borland.com/bcppbuilder/freecompiler/
+
+
+What is new:
+
+    + Package should compile out of the box under CygWin
+
+    + Added makefiles and changes to use Borland C++ compiler
+under WIN32 as well as VC++ 6.0
+
+    + Fix Abyss.dsp to use the proper thread safe libraries,
+and updated to VC++ 6.0
+
+    + Fixed thread leaks ( handles )
+
+
+
+Applying the patch to Abyss-0.3.tar.gz
+--------------------------------------
+
+   + get archive from here:
+       http://abyss.linuxave.net/abyss-0.3.tar.gz
+WARNING: this site seems to be dead for the last two months.
+
+   + cd /work  ( any dir )
+     tar xzvf abyss-0.3.tar.gz
+        cd abyss
+        patch -p1 <abyss-0.3-20010131.patch
+
+
+What to do next:
+
+
+   a) Cygwin
+
+      cd abyss/src
+      make
+        
+
+   b) Borland C++
+
+      cd abyss\src
+      set BCC_PATH=<location where your compiler is located>
+      ( BCC_PATH=d:\bcb5 )
+
+      make -f makefile.bcc32
+
+   c) VC++ 6.0                 
+      cd abyss\src
+      msdev Abyss.dsp
+      ( Or just open the workspace with Visual Studio, and you know
+       the drill ).
+NOTE: Under Cygwin, after I apply the patch, Visual Studio was unable to
+recognize the workspace. ???
+
+
+List of changes done to the ABYSS http server: ( ChangesLog )
+----------------------------------------------
+
+ + changed _WIN32 to ABYSS_WIN32. THis solve the problem that the
+macro _WIN32 is defined under CygWin. CygWin has a unix like
+api ( _UNIX ), so the macro _UNIX should be defined then.
+Under CygWin we would have _UNIX and _WIN32 defined at the same
+time.
+
+
+ + Theead API -- Added two extra functions: ThreadExit() and
+ThreadClose(). These allows the resources of the threads to be
+released when the thread has complete its duty serving the
+request.
+
+ + Added extra flag to TConn structure to make possible the
+management of the worker threads by the server.
+
+
+ + Changed allocation of TConn array from stack to heap. This
+would cause problems on certain system ( specially embedded systems ),
+where the stack sizes arr not that large.
+
+ + Changed ServerRun to free thread resources when the connection
+for the thread is closed.
+
+ + Changed main.c to make the sginal registration conforming with
+the usage of the _FORK option.
+
+ + Change ThreadCreate to be able to specify the "stack size" of the
+worker's threads ( pthread ). Defined lable for it.
+
+
+ + Added flag _NO_USERS to disable check for users and groups.
+This is useful for embedded systems where no users are available.
+
+ + Updated VC++ workspace to version 6.0
+
+
+ + Changed the creation of the thread under WIN32 to use a RTL
+function ( _beginthreadex ), as recommend by MS, instead of using 
+the naked WIN32 API.
+
+-- 
+Rosimildo da Silva            rdasilva@connectel.com 
+ConnectTel, Inc.              Austin, TX -- USA      
+Phone : 512-338-1111          Fax : 512-918-0449     
+Company Page:  http://www.connecttel.com             
+Home Page:     http://members.nbci.com/rosimildo/
diff --git a/lib/abyss/readme.txt b/lib/abyss/readme.txt
new file mode 100644 (file)
index 0000000..c42ca1f
--- /dev/null
@@ -0,0 +1,160 @@
+
+
+                              ABYSS Web Server
+                             ------------------
+
+
+About:
+------
+
+ABYSS aims to be a fully HTTP/1.1 compliant web server. Its main design
+goals are speed, low resource usage and portability. ABYSS works on most
+UNIX based systems and on Win32 systems (Win95/98/2000/NT).
+
+Copyright:
+----------
+
+Copyright (C) 2000 Moez Mahfoudh. All rights reserved.
+
+Status:
+-------
+
+ABYSS is still in development stage. Actual version is 0.3. Many features
+are not implemented yet but the server core works well and seems to be
+stable. It is fully reliable for serving static files on medium load sites.
+In fact, primary benchmarks show that ABYSS is 70% as fast as Apache when
+using the fork system. This rate jumps to 130% when using threads.
+On UNIX platforms, some problems occurred because of the use of the Pthreads
+library. This will be corrected in the future versions. That's why only the
+fork system is usable under UNIX. This lowers performances but guarantees
+stability.
+CGI/1.1 support is still absent from the current version but will be
+included in the near future.
+
+Change Log:
+-----------
+
+   * Version 0.3 (March 23,2000):
+        o Handles conditional GET requests (by date)
+        o Conforms to all the MUSTs of the RFC2616 (newer version of the
+          HTTP/1.1 protocol draft)
+        o New configuration options (such as pidfile for UNIX systems...)
+        o Handles HEAD and OPTIONS methods
+        o Many bug fixes
+        o Tested on Sun-OS 5.7
+        o Second public release
+
+   * Version 0.2 beta (February 7,2000):
+        o Handles GET on static files
+        o Handles correctly range requests
+        o Conforms to 80% of the MUSTs of the RFC2068 (HTTP/1.1 protocol
+          draft)
+        o Improved code portability (Win32 and UNIX platforms)
+        o Tested on Linux 2.2 and Win95/98
+        o First public release
+
+   * Version 0.1 (January 2000):
+        o Completely rewritten in C
+        o Speed improvement
+        o New memory allocation scheme (using pools)
+        o Never released
+
+   * Version 0.0 (January 2000):
+        o Initial version
+        o Written in C++
+        o Never released
+
+Downloading:
+------------
+
+   * Version 0.3 (current version):
+        o UNIX package (source) abyss-0.3.tar.gz.
+        o Win32 package is not available but you can extract source files
+          from the UNIX package and compile them on Windows without any
+          modification. (Sorry for this inconvenience: I have no Windows
+          machine now to compile the program and to test it. If someone can
+          do that, please email me the zipped package and I'll add it here).
+
+   * Version 0.2 beta:
+        o UNIX package (source) abyss-0.2b.tar.gz.
+        o Win32 package (source+binary) abyss-0.2b.zip.
+
+Installation:
+-------------
+
+   * For UNIX systems:
+        o Untar/Ungzip the distribution package with a command like tar xvfz
+          abyss-x.y.tar.gz
+        o Edit the Makefile src/Makefile to meet your system requirements.
+        o Go to directory src and execute make.
+        o The server binary is generated and stored in the bin directory.
+        o Edit the conf/abyss.conf to reflect your system configuration (At
+          least change the paths).
+        o Goto to the bin directory and start the server by typing ./abyss
+          -c ../conf/abyss.conf
+
+   * For Win32 systems:
+        o Unzip the distribution package.
+        o An executable file is already present in the bin directory.
+        o If you wish to recompile the server, open the src/abyss.dsw file
+          with Microsoft Visual C++ 5.0 or higher and rebuild the project.
+        o Edit the conf/abyss.conf to reflect your system configuration (At
+          least change the paths).
+        o Goto to the bin directory and start the server by typing ./abyss
+          -c ../conf/abyss.conf
+
+Configuration:
+--------------
+
+Edit the conf/abyss.conf file and change the values of the available
+options.
+
+Bugs:
+-----
+
+Please email bug reports to mmoez@bigfoot.com
+
+To do:
+------
+
+   * CGI/1.1 support
+   * Web based configuration/administration
+   * Speed improvement
+   * File caching system
+   * Throttling
+   * PUT method handling
+   * ...
+
+License:
+--------
+
+ABYSS Web Server is licensed under a modified BSD type license:
+
+     Copyright (C) 2000 Moez Mahfoudh. All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, are permitted provided that the following conditions
+     are met:
+
+        * Redistributions of source code must retain the above
+          copyright notice, this list of conditions and the following
+          disclaimer.
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials
+          provided with the distribution.
+        * The name of the author may not be used to endorse or promote
+          products derived from this software without specific prior
+          written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+     OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/abyss/src/Abyss.dsp b/lib/abyss/src/Abyss.dsp
new file mode 100644 (file)
index 0000000..dad1e38
--- /dev/null
@@ -0,0 +1,134 @@
+# Microsoft Developer Studio Project File - Name="Abyss" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=Abyss - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Abyss.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "Abyss.mak" CFG="Abyss - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "Abyss - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "Abyss - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "Abyss - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "../bin"\r
+# PROP Intermediate_Dir "objs"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../include" /I "../../../.." /I "../../.." /I "../../../include" /I "../../../lib/util/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c\r
+# ADD BASE RSC /l 0x40c /d "NDEBUG"\r
+# ADD RSC /l 0x40c /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib ..\..\xmlrpc.lib /nologo /subsystem:console /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "Abyss - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "../bin"\r
+# PROP Intermediate_Dir "objs"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../../.." /I "../../.." /I "../../../include" /I "../../../lib/util/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c\r
+# ADD BASE RSC /l 0x40c /d "_DEBUG"\r
+# ADD RSC /l 0x40c /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib wsock32.lib ..\..\xmlrpcD.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "Abyss - Win32 Release"\r
+# Name "Abyss - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "c"\r
+# Begin Source File\r
+\r
+SOURCE=.\conf.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\conn.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\data.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\file.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\http.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\main.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\server.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\socket.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\trace.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h"\r
+# Begin Source File\r
+\r
+SOURCE=.\abyss.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/lib/abyss/src/Abyss.dsw b/lib/abyss/src/Abyss.dsw
new file mode 100644 (file)
index 0000000..4e27c99
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Abyss"=.\Abyss.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/abyss/src/Makefile b/lib/abyss/src/Makefile
new file mode 100644 (file)
index 0000000..b8b4db3
--- /dev/null
@@ -0,0 +1,73 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../../..
+endif
+SUBDIR = lib/abyss/src
+
+include $(SRCDIR)/Makefile.config
+
+CFLAGS = $(CFLAGS_COMMON)
+CFLAGS += -D_UNIX
+ifeq ($(ENABLE_ABYSS_THREADS),yes)
+  THREAD_MODULE = thread_pthread
+else
+  THREAD_MODULE = thread_fork
+endif
+CFLAGS += $(CFLAGS_PERSONAL) $(CADD)
+LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR)
+LIBLDFLAGS += $(LADD)
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include
+
+LTLIBRARIES_TO_INSTALL = libxmlrpc_abyss.la
+
+default: all
+
+.PHONY: all
+all: libxmlrpc_abyss.la
+
+
+ABYSS_OBJS = \
+  conf.lo \
+  conn.lo \
+  data.lo \
+  date.lo \
+  file.lo \
+  http.lo \
+  response.lo \
+  server.lo \
+  session.lo \
+  socket.lo \
+  socket_unix.lo \
+  token.lo \
+  $(THREAD_MODULE).lo \
+  trace.lo \
+
+
+libxmlrpc_abyss.la: $(ABYSS_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+
+$(ABYSS_OBJS):%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) \
+         $(CFLAGS) $<
+
+.PHONY: clean
+clean: clean-common
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: tags
+tags: TAGS
+
+.PHONY: distdir
+distdir:
+
+.PHONY: install
+install: install-common
+
+.PHONY: dep
+dep: dep-common
+
+include $(SRCDIR)/Makefile.common
+
+include Makefile.depend
diff --git a/lib/abyss/src/Makefile.depend b/lib/abyss/src/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/abyss/src/abyss_info.h b/lib/abyss/src/abyss_info.h
new file mode 100644 (file)
index 0000000..1d3db45
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef ABYSS_INFO_H_INCLUDED
+#define ABYSS_INFO_H_INCLUDED
+
+#define SERVER_VERSION      "1.06"
+
+#define SERVER_HVERSION     "XMLRPC_ABYSS/1.06"
+
+#define SERVER_HTML_INFO \
+  "<p><HR><b><i><a href=\"http:\057\057xmlrpc-c.sourceforge.net\">" \
+  "ABYSS Web Server for XML-RPC For C/C++</a></i></b> " \
+  "version "SERVER_VERSION"<br>" \
+  "</p>"
+
+#define SERVER_PLAIN_INFO \
+  CRLF "----------------------------------------" \
+       "----------------------------------------" \
+  CRLF "ABYSS Web Server for XML-RPC For C/C++ " \
+  "version "SERVER_VERSION CRLF"See xmlrpc-c.sourceforge.net"
+
+#endif
diff --git a/lib/abyss/src/conf.c b/lib/abyss/src/conf.c
new file mode 100644 (file)
index 0000000..84d7c97
--- /dev/null
@@ -0,0 +1,379 @@
+/******************************************************************************
+**
+** conf.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined(WIN32) && !defined(__BORLANDC__)
+#include <direct.h>
+#endif
+
+#ifdef _UNIX
+#include <pwd.h>
+#endif
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+#include "trace.h"
+#include "server.h"
+#include "http.h"
+
+/*********************************************************************
+** Configuration Files Parsing Functions
+*********************************************************************/
+
+
+
+static abyss_bool
+ConfReadLine(TFile *f,char *buffer,uint32_t len) {
+    abyss_bool r=TRUE;
+    char c,*p,*z=buffer;
+
+    while ((--len)>0)
+    {
+        if (FileRead(f,buffer,1)<1)
+        {
+            if (z==buffer)
+                r=FALSE;
+            break;
+        };
+
+        if ((*buffer==CR) || (*buffer==LF) )
+            break;
+
+        buffer++;
+    };
+
+    if (len==0)
+        while (FileRead(f,&c,1)==1)
+            if ((c==CR) || (c==LF))
+                break;
+
+    *buffer='\0';
+
+    /* Discard comments */
+    p=strchr(z,'#');
+    if (p)
+        *p='\0';
+
+    return r;
+}
+
+static abyss_bool
+ConfNextToken(char **p) {
+    while (1)
+        switch (**p)
+        {
+        case '\t':
+        case ' ':
+            (*p)++;
+            break;
+        case '\0':
+            return FALSE;
+        default:
+            return TRUE;
+        };
+}
+
+static char *
+ConfGetToken(char **p) {
+    char *p0=*p;
+
+    while (1)
+        switch (**p)
+        {
+        case '\t':
+        case ' ':
+        case CR:
+        case LF:
+        case '\0':
+            if (p0==*p)
+                return NULL;
+
+            if (**p)
+            {
+                **p='\0';
+                (*p)++;
+            };
+            return p0;
+
+        default:
+            (*p)++;
+        };
+}
+
+static abyss_bool
+ConfReadInt(const char * const p,
+            int32_t *    const n,
+            int32_t      const min,
+            int32_t      const max) {
+/*----------------------------------------------------------------------------
+   Convert string 'p' to integer *n.
+
+   If it isn't a valid integer or is not with the bounds [min, max],
+   return FALSE.  Otherwise, return TRUE.
+-----------------------------------------------------------------------------*/
+    char * e;
+
+    *n = strtol(p, &e, 10);
+
+    if (min != max)
+        return ((e != p) && (*n >= min) && (*n <= max));
+    else
+        return (e != p);
+}
+
+
+
+static abyss_bool
+ConfReadBool(char *p, abyss_bool *b) {
+    if (strcasecmp(p,"yes")==0)
+    {
+        *b=TRUE;
+        return TRUE;
+    };
+
+    if (strcasecmp(p,"no")==0)
+    {
+        *b=FALSE;
+        return TRUE;
+    };
+
+    return FALSE;
+}
+
+/*********************************************************************
+** MIME Types File
+*********************************************************************/
+
+static void
+readMIMETypesFile(const char * const filename,
+                  MIMEType **  const MIMETypePP) {
+
+    abyss_bool success;
+    MIMEType * MIMETypeP;
+
+    MIMETypeP = MIMETypeCreate();
+    if (MIMETypeP) {
+        TFile file;
+        abyss_bool fileOpened;
+
+        fileOpened = FileOpen(&file, filename, O_RDONLY);
+        if (fileOpened) {
+            char z[512];
+            while (ConfReadLine(&file, z, 512)) {
+                char * p;
+                p = &z[0];
+            
+                if (ConfNextToken(&p)) {
+                    const char * mimetype = ConfGetToken(&p);
+                    if (mimetype) {
+                        while (ConfNextToken(&p)) {
+                            const char * const ext = ConfGetToken(&p);
+                            if (ext)
+                                MIMETypeAdd2(MIMETypeP, mimetype, ext);
+                            else
+                                break;
+                        }
+                    }
+                }
+            }
+            FileClose(&file);
+            success = TRUE;
+        } else
+            success = FALSE;
+        if (!success)
+            MIMETypeDestroy(MIMETypeP);
+    } else
+        success = FALSE;
+
+    if (success)
+        *MIMETypePP = MIMETypeP;
+    else
+        *MIMETypePP = NULL;
+}
+
+/*********************************************************************
+** Server Configuration File
+*********************************************************************/
+
+static void
+chdirx(const char * const newdir,
+       abyss_bool * const successP) {
+    
+#if defined(WIN32) && !defined(__BORLANDC__)
+    *successP = _chdir(newdir) == 0;
+#else
+    *successP = chdir(newdir) == 0;
+#endif
+}
+
+
+
+static void
+parseUser(const char *      const p, 
+          struct _TServer * const srvP) {
+#ifdef _UNIX
+    if (p[0] == '#') {
+        int32_t n;
+        
+        if (!ConfReadInt(&p[1], &n, 0, 0))
+            TraceExit("Bad user number '%s'", p);
+        else
+            srvP->uid = n;
+    } else {
+        struct passwd * pwd;
+
+        if (!(pwd = getpwnam(p)))
+            TraceExit("Unknown user '%s'", p);
+        
+        srvP->uid = pwd->pw_uid;
+        if ((int)srvP->gid==(-1))
+            srvP->gid = pwd->pw_gid;
+    };
+#else
+    TraceMsg("User option ignored");
+#endif  /* _UNIX */ 
+}
+
+
+
+static void
+parsePidfile(const char *      const p,
+             struct _TServer * const srvP) {
+#ifdef _UNIX
+    if (!FileOpenCreate(&srvP->pidfile, p, O_TRUNC | O_WRONLY)) {
+        srvP->pidfile = -1;
+        TraceMsg("Bad PidFile value '%s'", p);
+    };
+#else
+    TraceMsg("PidFile option ignored");
+#endif  /* _UNIX */ 
+}
+
+
+
+abyss_bool
+ConfReadServerFile(const char * const filename,
+                   TServer *    const serverP) {
+
+    struct _TServer * const srvP = serverP->srvP;
+
+    TFile f;
+    char z[512];
+    char * p;
+    unsigned int lineNum;
+    TFileStat fs;
+
+    if (!FileOpen(&f, filename, O_RDONLY))
+        return FALSE;
+
+    lineNum = 0;
+
+    while (ConfReadLine(&f, z, 512)) {
+        ++lineNum;
+        p = z;
+
+        if (ConfNextToken(&p)) {
+            const char * const option = ConfGetToken(&p);
+            if (option) {
+                ConfNextToken(&p);
+
+                if (strcasecmp(option, "port") == 0) {
+                    int32_t n;
+                    if (ConfReadInt(p, &n, 1, 65535))
+                        srvP->port = n;
+                    else
+                        TraceExit("Invalid port '%s'", p);
+                } else if (strcasecmp(option, "serverroot") == 0) {
+                    abyss_bool success;
+                    chdirx(p, &success);
+                    if (!success)
+                        TraceExit("Invalid server root '%s'",p);
+                } else if (strcasecmp(option, "path") == 0) {
+                    if (FileStat(p, &fs))
+                        if (fs.st_mode & S_IFDIR) {
+                            xmlrpc_strfree(srvP->filespath);
+                            srvP->filespath = strdup(p);
+                            continue;
+                        }
+                    TraceExit("Invalid path '%s'", p);
+                } else if (strcasecmp(option, "default") == 0) {
+                    const char * filename;
+                    
+                    while ((filename = ConfGetToken(&p))) {
+                        ListAdd(&srvP->defaultfilenames, strdup(filename));
+                        if (!ConfNextToken(&p))
+                            break;
+                    }
+                } else if (strcasecmp(option, "keepalive") == 0) {
+                    int32_t n;
+                    if (ConfReadInt(p, &n, 1, 65535))
+                        srvP->keepalivemaxconn = n;
+                    else
+                        TraceExit("Invalid KeepAlive value '%s'", p);
+                } else if (strcasecmp(option, "timeout") == 0) {
+                    int32_t n;
+                    if (ConfReadInt(p, &n, 1, 3600)) {
+                        srvP->keepalivetimeout = n;
+                        /* Must see what to do with that */
+                        srvP->timeout = n;
+                    } else
+                        TraceExit("Invalid TimeOut value '%s'", p);
+                } else if (strcasecmp(option, "mimetypes") == 0) {
+                    readMIMETypesFile(p, &srvP->mimeTypeP);
+                    if (!srvP->mimeTypeP)
+                        TraceExit("Can't read MIME Types file '%s'", p);
+                } else if (strcasecmp(option,"logfile") == 0) {
+                    srvP->logfilename = strdup(p);
+                } else if (strcasecmp(option,"user") == 0) {
+                    parseUser(p, srvP);
+                } else if (strcasecmp(option, "pidfile")==0) {
+                    parsePidfile(p, srvP);
+                } else if (strcasecmp(option, "advertiseserver") == 0) {
+                    if (!ConfReadBool(p, &srvP->advertise))
+                        TraceExit("Invalid boolean value "
+                                  "for AdvertiseServer option");
+                } else
+                    TraceExit("Invalid option '%s' at line %u",
+                              option, lineNum);
+            }
+        }
+    }
+
+    FileClose(&f);
+    return TRUE;
+}
diff --git a/lib/abyss/src/conn.c b/lib/abyss/src/conn.c
new file mode 100644 (file)
index 0000000..ab86fd3
--- /dev/null
@@ -0,0 +1,637 @@
+/* Copyright information is at the end of the file. */
+
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "mallocvar.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/sleep_int.h"
+#include "xmlrpc-c/abyss.h"
+#include "socket.h"
+#include "server.h"
+#include "thread.h"
+
+#include "conn.h"
+
+/*********************************************************************
+** Conn
+*********************************************************************/
+
+static TThreadProc connJob;
+
+static void
+connJob(void * const userHandle) {
+/*----------------------------------------------------------------------------
+   This is the root function for a thread that processes a connection
+   (performs HTTP transactions).
+-----------------------------------------------------------------------------*/
+    TConn * const connectionP = userHandle;
+
+    (connectionP->job)(connectionP);
+
+    connectionP->finished = TRUE;
+        /* Note that if we are running in a forked process, setting
+           connectionP->finished has no effect, because it's just our own
+           copy of *connectionP.  In this case, Parent must update his own
+           copy based on a SIGCHLD signal that the OS will generate right
+           after we exit.
+        */
+
+    ThreadExit(0);
+}
+
+
+
+static void
+connDone(TConn * const connectionP) {
+
+    /* In the forked case, this is designed to run in the parent
+       process after the child has terminated.
+    */
+    connectionP->finished = TRUE;
+
+    if (connectionP->done)
+        connectionP->done(connectionP);
+}
+
+
+
+static TThreadDoneFn threadDone;
+
+static void
+threadDone(void * const userHandle) {
+
+    TConn * const connectionP = userHandle;
+    
+    connDone(connectionP);
+}
+
+
+
+static void
+makeThread(TConn *             const connectionP,
+           enum abyss_foreback const foregroundBackground,
+           abyss_bool          const useSigchld,
+           const char **       const errorP) {
+           
+    switch (foregroundBackground) {
+    case ABYSS_FOREGROUND:
+        connectionP->hasOwnThread = FALSE;
+        *errorP = NULL;
+        break;
+    case ABYSS_BACKGROUND: {
+        const char * error;
+        connectionP->hasOwnThread = TRUE;
+        ThreadCreate(&connectionP->threadP, connectionP,
+                     &connJob, &threadDone, useSigchld,
+                     &error);
+        if (error) {
+            xmlrpc_asprintf(errorP, "Unable to create thread to "
+                            "process connection.  %s", error);
+            xmlrpc_strfree(error);
+        } else
+            *errorP = NULL;
+    } break;
+    } /* switch */
+}
+
+    
+
+void
+ConnCreate(TConn **            const connectionPP,
+           TServer *           const serverP,
+           TSocket *           const connectedSocketP,
+           TThreadProc *       const job,
+           TThreadDoneFn *     const done,
+           enum abyss_foreback const foregroundBackground,
+           abyss_bool          const useSigchld,
+           const char **       const errorP) {
+/*----------------------------------------------------------------------------
+   Create an HTTP connection.
+
+   A connection carries one or more HTTP transactions (request/response).
+
+   'connectedSocketP' transports the requests and responses.
+
+   The connection handles those HTTP requests.
+
+   The connection handles the requests primarily by running the
+   function 'job' once.  Some connections can do that autonomously, as
+   soon as the connection is created.  Others don't until Caller
+   subsequently calls ConnProcess.  Some connections complete the
+   processing before ConnProcess return, while others may run the
+   connection asynchronously to the creator, in the background, via a
+   TThread thread.  'foregroundBackground' determines which.
+
+   'job' calls methods of the connection to get requests and send
+   responses.
+
+   Some time after the HTTP transactions are all done, 'done' gets
+   called in some context.
+-----------------------------------------------------------------------------*/
+    TConn * connectionP;
+
+    MALLOCVAR(connectionP);
+
+    if (connectionP == NULL)
+        xmlrpc_asprintf(errorP, "Unable to allocate memory for a connection "
+                        "descriptor.");
+    else {
+        abyss_bool success;
+        uint16_t peerPortNumber;
+
+        connectionP->server     = serverP;
+        connectionP->socketP    = connectedSocketP;
+        connectionP->buffersize = 0;
+        connectionP->bufferpos  = 0;
+        connectionP->finished   = FALSE;
+        connectionP->job        = job;
+        connectionP->done       = done;
+        connectionP->inbytes    = 0;
+        connectionP->outbytes   = 0;
+        connectionP->trace      = getenv("ABYSS_TRACE_CONN");
+
+        SocketGetPeerName(connectedSocketP,
+                          &connectionP->peerip, &peerPortNumber, &success);
+
+        if (success)
+            makeThread(connectionP, foregroundBackground, useSigchld, errorP);
+        else
+            xmlrpc_asprintf(errorP, "Failed to get peer name from socket.");
+    }
+    *connectionPP = connectionP;
+}
+
+
+
+abyss_bool
+ConnProcess(TConn * const connectionP) {
+/*----------------------------------------------------------------------------
+   Drive the main processing of a connection -- run the connection's
+   "job" function, which should read HTTP requests from the connection
+   and send HTTP responses.
+
+   If we succeed, we guarantee the connection's "done" function will get
+   called some time after all processing is complete.  It might be before
+   we return or some time after.  If we fail, we guarantee the "done"
+   function will not be called.
+-----------------------------------------------------------------------------*/
+    abyss_bool retval;
+
+    if (connectionP->hasOwnThread) {
+        /* There's a background thread to handle this connection.  Set
+           it running.
+        */
+        retval = ThreadRun(connectionP->threadP);
+    } else {
+        /* No background thread.  We just handle it here while Caller waits. */
+        (connectionP->job)(connectionP);
+        connDone(connectionP);
+        retval = TRUE;
+    }
+    return retval;
+}
+
+
+
+void
+ConnWaitAndRelease(TConn * const connectionP) {
+    if (connectionP->hasOwnThread)
+        ThreadWaitAndRelease(connectionP->threadP);
+    
+    free(connectionP);
+}
+
+
+
+abyss_bool
+ConnKill(TConn * connectionP) {
+    connectionP->finished = TRUE;
+    return ThreadKill(connectionP->threadP);
+}
+
+
+
+void
+ConnReadInit(TConn * const connectionP) {
+    if (connectionP->buffersize>connectionP->bufferpos) {
+        connectionP->buffersize -= connectionP->bufferpos;
+        memmove(connectionP->buffer,
+                connectionP->buffer+connectionP->bufferpos,
+                connectionP->buffersize);
+        connectionP->bufferpos = 0;
+    } else
+        connectionP->buffersize=connectionP->bufferpos = 0;
+
+    connectionP->inbytes=connectionP->outbytes = 0;
+}
+
+
+
+static void
+traceBuffer(const char * const label,
+            const char * const buffer,
+            unsigned int const size) {
+
+    unsigned int nonPrintableCount;
+    unsigned int i;
+    
+    nonPrintableCount = 0;  /* Initial value */
+    
+    for (i = 0; i < size; ++i) {
+        if (!isprint(buffer[i]) && buffer[i] != '\n' && buffer[i] != '\r')
+            ++nonPrintableCount;
+    }
+    if (nonPrintableCount > 0)
+        fprintf(stderr, "%s contains %u nonprintable characters.\n", 
+                label, nonPrintableCount);
+    
+    fprintf(stderr, "%s:\n", label);
+    fprintf(stderr, "%.*s\n", (int)size, buffer);
+}
+
+
+
+static void
+traceSocketRead(TConn *      const connectionP,
+                unsigned int const size) {
+
+    if (connectionP->trace)
+        traceBuffer("READ FROM SOCKET",
+                    connectionP->buffer + connectionP->buffersize, size);
+}
+
+
+
+static void
+traceSocketWrite(TConn *      const connectionP,
+                 const char * const buffer,
+                 unsigned int const size,
+                 abyss_bool   const failed) {
+
+    if (connectionP->trace) {
+        const char * const label =
+            failed ? "FAILED TO WRITE TO SOCKET" : "WROTE TO SOCKET";
+        traceBuffer(label, buffer, size);
+    }
+}
+
+
+
+static uint32_t
+bufferSpace(TConn * const connectionP) {
+    
+    return BUFFER_SIZE - connectionP->buffersize;
+}
+                    
+
+
+abyss_bool
+ConnRead(TConn *  const connectionP,
+         uint32_t const timeout) {
+/*----------------------------------------------------------------------------
+   Read some stuff on connection *connectionP from the socket.
+
+   Don't wait more than 'timeout' seconds for data to arrive.  Fail if
+   nothing arrives within that time.
+-----------------------------------------------------------------------------*/
+    time_t const deadline = time(NULL) + timeout;
+
+    abyss_bool cantGetData;
+    abyss_bool gotData;
+
+    cantGetData = FALSE;
+    gotData = FALSE;
+    
+    while (!gotData && !cantGetData) {
+        int const timeLeft = deadline - time(NULL);
+
+        if (timeLeft <= 0)
+            cantGetData = TRUE;
+        else {
+            int rc;
+            
+            rc = SocketWait(connectionP->socketP, TRUE, FALSE,
+                            timeLeft * 1000);
+            
+            if (rc != 1)
+                cantGetData = TRUE;
+            else {
+                uint32_t bytesAvail;
+            
+                bytesAvail = SocketAvailableReadBytes(connectionP->socketP);
+                
+                if (bytesAvail <= 0)
+                    cantGetData = TRUE;
+                else {
+                    uint32_t const bytesToRead =
+                        MIN(bytesAvail, bufferSpace(connectionP)-1);
+
+                    uint32_t bytesRead;
+
+                    bytesRead = SocketRead(
+                        connectionP->socketP,
+                        connectionP->buffer + connectionP->buffersize,
+                        bytesToRead);
+                    if (bytesRead > 0) {
+                        traceSocketRead(connectionP, bytesRead);
+                        connectionP->inbytes += bytesRead;
+                        connectionP->buffersize += bytesRead;
+                        connectionP->buffer[connectionP->buffersize] = '\0';
+                        gotData = TRUE;
+                    }
+                }
+            }
+        }
+    }
+    if (gotData)
+        return TRUE;
+    else
+        return FALSE;
+}
+
+
+            
+abyss_bool
+ConnWrite(TConn *      const connectionP,
+          const void * const buffer,
+          uint32_t     const size) {
+
+    abyss_bool failed;
+
+    SocketWrite(connectionP->socketP, buffer, size, &failed);
+
+    traceSocketWrite(connectionP, buffer, size, failed);
+
+    if (!failed)
+        connectionP->outbytes += size;
+
+    return !failed;
+}
+
+
+
+abyss_bool
+ConnWriteFromFile(TConn *  const connectionP,
+                  TFile *  const fileP,
+                  uint64_t const start,
+                  uint64_t const last,
+                  void *   const buffer,
+                  uint32_t const buffersize,
+                  uint32_t const rate) {
+/*----------------------------------------------------------------------------
+   Write the contents of the file stream *fileP, from offset 'start'
+   up through 'last', to the HTTP connection *connectionP.
+
+   Meter the reading so as not to read more than 'rate' bytes per second.
+
+   Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this.
+-----------------------------------------------------------------------------*/
+    abyss_bool retval;
+    uint32_t waittime;
+    abyss_bool success;
+    uint32_t readChunkSize;
+
+    if (rate > 0) {
+        readChunkSize = MIN(buffersize, rate);  /* One second's worth */
+        waittime = (1000 * buffersize) / rate;
+    } else {
+        readChunkSize = buffersize;
+        waittime = 0;
+    }
+
+    success = FileSeek(fileP, start, SEEK_SET);
+    if (!success)
+        retval = FALSE;
+    else {
+        uint64_t const totalBytesToRead = last - start + 1;
+        uint64_t bytesread;
+
+        bytesread = 0;  /* initial value */
+
+        while (bytesread < totalBytesToRead) {
+            uint64_t const bytesLeft = totalBytesToRead - bytesread;
+            uint64_t const bytesToRead = MIN(readChunkSize, bytesLeft);
+
+            uint64_t bytesReadThisTime;
+
+            bytesReadThisTime = FileRead(fileP, buffer, bytesToRead);
+            bytesread += bytesReadThisTime;
+            
+            if (bytesReadThisTime > 0)
+                ConnWrite(connectionP, buffer, bytesReadThisTime);
+            else
+                break;
+            
+            if (waittime > 0)
+                xmlrpc_millisecond_sleep(waittime);
+        }
+        retval = (bytesread >= totalBytesToRead);
+    }
+    return retval;
+}
+
+
+
+static void
+processHeaderLine(char *       const start,
+                  const char * const headerStart,
+                  TConn *      const connectionP,                  
+                  time_t       const deadline,
+                  abyss_bool * const gotHeaderP,
+                  char **      const nextP,
+                  abyss_bool * const errorP) {
+/*----------------------------------------------------------------------------
+  If there's enough data in the buffer, process a line of HTTP
+  header.
+
+  It is part of a header that starts at 'headerStart' and has been
+  previously processed up to the line starting at 'start'.  The data
+  in the buffer is terminated by a NUL.
+
+  Return as *nextP the location of the next header line to process
+  (same as 'start' if we didn't find a line to process).
+
+  WE MODIFY THE DATA.
+-----------------------------------------------------------------------------*/
+    abyss_bool gotHeader;
+    char * lfPos;
+    char * p;
+
+    p = start;
+
+    gotHeader = FALSE;  /* initial assumption */
+
+    lfPos = strchr(p, LF);
+    if (lfPos) {
+        if ((*p != LF) && (*p != CR)) {
+            /* We're looking at a non-empty line */
+            if (*(lfPos+1) == '\0') {
+                /* There's nothing in the buffer after the line, so we
+                   don't know if there's a continuation line coming.
+                   Must read more.
+                */
+                int const timeLeft = deadline - time(NULL);
+                
+                *errorP = !ConnRead(connectionP, timeLeft);
+            }
+            if (!*errorP) {
+                p = lfPos; /* Point to LF */
+                
+                /* If the next line starts with whitespace, it's a
+                   continuation line, so blank out the line
+                   delimiter (LF or CRLF) so as to join the next
+                   line with this one.
+                */
+                if ((*(p+1) == ' ') || (*(p+1) == '\t')) {
+                    if (p > headerStart && *(p-1) == CR)
+                        *(p-1) = ' ';
+                    *p++ = ' ';
+                } else
+                    gotHeader = TRUE;
+            }
+        } else {
+            /* We're looking at an empty line (i.e. what marks the
+               end of the header)
+            */
+            p = lfPos;  /* Point to LF */
+            gotHeader = TRUE;
+        }
+    }
+
+    if (gotHeader) {
+        /* 'p' points to the final LF */
+
+        /* Replace the LF or the CR in CRLF with NUL, so as to terminate
+           the string at 'headerStart' that is the full header.
+        */
+        if (p > headerStart && *(p-1) == CR)
+            *(p-1) = '\0';  /* NUL out CR in CRLF */
+        else
+            *p = '\0';  /* NUL out LF */
+
+        ++p;  /* Point to next line in buffer */
+    }
+    *gotHeaderP = gotHeader;
+    *nextP = p;
+}
+
+
+
+abyss_bool
+ConnReadHeader(TConn * const connectionP,
+               char ** const headerP) {
+/*----------------------------------------------------------------------------
+   Read an HTTP header on connection *connectionP.
+
+   An HTTP header is basically a line, except that if a line starts
+   with white space, it's a continuation of the previous line.  A line
+   is delimited by either LF or CRLF.
+
+   In the course of reading, we read at least one character past the
+   line delimiter at the end of the header; we may read much more.  We
+   leave everything after the header (and its line delimiter) in the
+   internal buffer, with the buffer pointer pointing to it.
+
+   We use stuff already in the internal buffer (perhaps left by a
+   previous call to this subroutine) before reading any more from from
+   the socket.
+
+   Return as *headerP the header value.  This is in the connection's
+   internal buffer.  This contains no line delimiters.
+-----------------------------------------------------------------------------*/
+    uint32_t const deadline = time(NULL) + connectionP->server->srvP->timeout;
+
+    abyss_bool retval;
+    char * p;
+    char * headerStart;
+    abyss_bool error;
+    abyss_bool gotHeader;
+
+    p = connectionP->buffer + connectionP->bufferpos;
+    headerStart = p;
+
+    gotHeader = FALSE;
+    error = FALSE;
+
+    while (!gotHeader && !error) {
+        int const timeLeft = deadline - time(NULL);
+
+        if (timeLeft <= 0)
+            error = TRUE;
+        else {
+            if (p >= connectionP->buffer + connectionP->buffersize
+                || !strchr(p, LF))
+                /* There is no line yet in the buffer.
+                   Need more data from the socket to chew on
+                */
+                error = !ConnRead(connectionP, timeLeft);
+
+            if (!error) {
+                assert(connectionP->buffer + connectionP->buffersize > p);
+                processHeaderLine(p, headerStart, connectionP, deadline,
+                                  &gotHeader, &p, &error);
+            }
+        }
+    }
+    if (gotHeader) {
+        /* We've consumed this part of the buffer (but be careful --
+           you can't reuse that part of the buffer because the string
+           we're returning is in it!
+        */
+        connectionP->bufferpos += p - headerStart;
+        *headerP = headerStart;
+        retval = TRUE;
+    } else
+        retval = FALSE;
+
+    return retval;
+}
+
+
+
+TServer *
+ConnServer(TConn * const connectionP) {
+    return connectionP->server;
+}
+
+
+
+/*******************************************************************************
+**
+** conn.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
diff --git a/lib/abyss/src/conn.h b/lib/abyss/src/conn.h
new file mode 100644 (file)
index 0000000..662b748
--- /dev/null
@@ -0,0 +1,98 @@
+#ifndef CONN_H_INCLUDED
+#define CONN_H_INCLUDED
+
+#include "xmlrpc-c/abyss.h"
+#include "socket.h"
+#include "file.h"
+
+#define BUFFER_SIZE 4096 
+
+struct _TConn {
+    struct _TConn * nextOutstandingP;
+        /* Link to the next connection in the list of outstanding
+           connections
+        */
+    TServer * server;
+    uint32_t buffersize;
+        /* Index into the connection buffer (buffer[], below) where
+           the next byte read on the connection will go.
+        */
+    uint32_t bufferpos;
+        /* Index into the connection buffer (buffer[], below) where
+           the next byte to be delivered to the user is.
+        */
+    uint32_t inbytes,outbytes;  
+    TSocket * socketP;
+    TIPAddr peerip;
+    abyss_bool hasOwnThread;
+    TThread * threadP;
+    abyss_bool finished;
+        /* We have done all the processing there is to do on this
+           connection, other than possibly notifying someone that we're
+           done.  One thing this signifies is that any thread or process
+           that the connection spawned is dead or will be dead soon, so
+           one could reasonably wait for it to be dead, e.g. with
+           pthread_join().  Note that one can scan a bunch of processes
+           for 'finished' status, but sometimes can't scan a bunch of
+           threads for liveness.
+        */
+    const char * trace;
+    TThreadProc * job;
+    TThreadDoneFn * done;
+    char buffer[BUFFER_SIZE];
+};
+
+typedef struct _TConn TConn;
+
+TConn * ConnAlloc(void);
+
+void ConnFree(TConn * const connectionP);
+
+void
+ConnCreate(TConn **            const connectionPP,
+           TServer *           const serverP,
+           TSocket *           const connectedSocketP,
+           TThreadProc *       const job,
+           TThreadDoneFn *     const done,
+           enum abyss_foreback const foregroundBackground,
+           abyss_bool          const useSigchld,
+           const char **       const errorP);
+
+abyss_bool
+ConnProcess(TConn * const connectionP);
+
+abyss_bool
+ConnKill(TConn * const connectionP);
+
+void
+ConnWaitAndRelease(TConn * const connectionP);
+
+abyss_bool
+ConnWrite(TConn *      const connectionP,
+          const void * const buffer,
+          uint32_t     const size);
+
+abyss_bool
+ConnRead(TConn *  const c,
+         uint32_t const timems);
+
+void
+ConnReadInit(TConn * const connectionP);
+
+abyss_bool
+ConnReadHeader(TConn * const connectionP,
+               char ** const headerP);
+
+abyss_bool
+ConnWriteFromFile(TConn *  const connectionP,
+                  TFile *  const file,
+                  uint64_t const start,
+                  uint64_t const end,
+                  void *   const buffer,
+                  uint32_t const buffersize,
+                  uint32_t const rate);
+
+TServer *
+ConnServer(TConn * const connectionP);
+
+#endif
diff --git a/lib/abyss/src/data.c b/lib/abyss/src/data.c
new file mode 100644 (file)
index 0000000..03f4c3f
--- /dev/null
@@ -0,0 +1,640 @@
+/******************************************************************************
+**
+** list.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+*******************************************************************************/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mallocvar.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+
+#include "xmlrpc-c/abyss.h"
+
+#include "token.h"
+
+#include "data.h"
+
+/*********************************************************************
+** List
+*********************************************************************/
+
+void ListInit(TList *sl)
+{
+    sl->item=NULL;
+    sl->size=sl->maxsize=0;
+    sl->autofree=FALSE;
+}
+
+void ListInitAutoFree(TList *sl)
+{
+    sl->item=NULL;
+    sl->size=sl->maxsize=0;
+    sl->autofree=TRUE;
+}
+
+
+
+void
+ListFree(TList * const sl) {
+
+    if (sl->item) {
+        if (sl->autofree) {
+            unsigned int i;
+            for (i = sl->size; i > 0; --i)
+                free(sl->item[i-1]);
+            
+        }
+        free(sl->item);
+    }
+    sl->item = NULL;
+    sl->size = 0;
+    sl->maxsize = 0;
+}
+
+
+
+void
+ListFreeItems(TList * const sl) {
+
+    if (sl->item) {
+        unsigned int i;
+        for (i = sl->size; i > 0; --i)
+            free(sl->item[i-1]);
+    }
+}
+
+
+
+abyss_bool
+ListAdd(TList * const sl,
+        void *  const str) {
+/*----------------------------------------------------------------------------
+   Add an item to the end of the list.
+-----------------------------------------------------------------------------*/
+    abyss_bool success;
+
+    if (sl->size >= sl->maxsize) {
+        uint16_t newSize = sl->maxsize + 16;
+        void **newitem;
+        
+        newitem = realloc(sl->item, newSize * sizeof(void *));
+        if (newitem) {
+            sl->item    = newitem;
+            sl->maxsize = newSize;
+        }
+    }
+
+    if (sl->size >= sl->maxsize)
+        success = FALSE;
+    else {
+        success = TRUE;
+        sl->item[sl->size++] = str;
+    }
+    return success;
+}
+
+
+
+void
+ListRemove(TList * const sl) {
+/*----------------------------------------------------------------------------
+   Remove the last item from the list.
+-----------------------------------------------------------------------------*/
+
+    assert(sl->size > 0);
+
+    --sl->size;
+}
+
+
+
+abyss_bool
+ListAddFromString(TList *      const list,
+                  const char * const stringArg) {
+
+    abyss_bool retval;
+    
+    if (!stringArg)
+        retval = TRUE;
+    else {
+        char * buffer;
+        
+        buffer = strdup(stringArg);
+        if (!buffer)
+            retval = FALSE;
+        else {
+            abyss_bool endOfString;
+            abyss_bool error;
+            char * c;
+
+            for (c = &buffer[0], endOfString = FALSE, error = FALSE;
+                 !endOfString && !error;
+                ) {
+                const char * t;
+                NextToken((const char **)&c);
+                
+                while (*c == ',')
+                    ++c;
+                
+                t = GetToken(&c);
+                if (!t)
+                    endOfString = TRUE;
+                else {
+                    char * p;
+
+                    for (p = c - 2; *p == ','; --p)
+                        *p = '\0';
+                    
+                    if (t[0] != '\0') {
+                        abyss_bool added;
+                        added = ListAdd(list, (void*)t);
+                        
+                        if (!added)
+                            error = TRUE;
+                    }
+                }
+            }
+            retval = !error;
+            xmlrpc_strfree(buffer);
+        }
+    }
+    return retval;
+}
+
+
+
+abyss_bool
+ListFindString(TList *      const sl,
+               const char * const str,
+               uint16_t *   const indexP)
+{
+    uint16_t i;
+
+    if (sl->item && str)
+        for (i=0;i<sl->size;i++)
+            if (strcmp(str,(char *)(sl->item[i]))==0)
+            {
+                *indexP=i;
+                return TRUE;
+            };
+
+    return FALSE;
+}
+
+/*********************************************************************
+** Buffer
+*********************************************************************/
+
+abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize)
+{
+    /* ************** Implement the static buffers ***/
+    buf->staticid=0;
+    buf->data=(void *)malloc(memsize);
+    if (buf->data)
+    {
+        buf->size=memsize;
+        return TRUE;
+    }
+    else
+    {
+        buf->size=0;
+        return FALSE;
+    };
+}
+
+void BufferFree(TBuffer *buf)
+{
+    if (buf->staticid)
+    {
+        /* ************** Implement the static buffers ***/
+    }
+    else
+        free(buf->data);
+
+    buf->size=0;
+    buf->staticid=0;
+}
+
+abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize)
+{
+    if (buf->staticid)
+    {
+        TBuffer b;
+
+        if (memsize<=buf->size)
+            return TRUE;
+
+        if (BufferAlloc(&b,memsize))
+        {
+            memcpy(b.data,buf->data,buf->size);
+            BufferFree(buf);
+            *buf=b;
+            return TRUE;
+        }
+    }
+    else
+    {
+        void *d;
+        
+        d=realloc(buf->data,memsize);
+        if (d)
+        {
+            buf->data=d;
+            buf->size=memsize;
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+
+/*********************************************************************
+** String
+*********************************************************************/
+
+abyss_bool StringAlloc(TString *s)
+{
+    s->size=0;
+    if (BufferAlloc(&(s->buffer),256))
+    {
+        *(char *)(s->buffer.data)='\0';
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
+
+abyss_bool StringConcat(TString *s,char *s2)
+{
+    uint32_t len=strlen(s2);
+
+    if (len+s->size+1>s->buffer.size)
+        if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
+            return FALSE;
+    
+    strcat((char *)(s->buffer.data),s2);
+    s->size+=len;
+    return TRUE;
+}
+
+abyss_bool StringBlockConcat(TString *s,char *s2,char **ref)
+{
+    uint32_t len=strlen(s2)+1;
+
+    if (len+s->size>s->buffer.size)
+        if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
+            return FALSE;
+    
+    *ref=(char *)(s->buffer.data)+s->size;
+    memcpy(*ref,s2,len);
+    s->size+=len;
+    return TRUE;
+}
+
+void StringFree(TString *s)
+{
+    s->size=0;
+    BufferFree(&(s->buffer));
+}
+
+char *StringData(TString *s)
+{
+    return (char *)(s->buffer.data);
+}
+
+/*********************************************************************
+** Hash
+*********************************************************************/
+
+static uint16_t
+Hash16(const char * const start) {
+
+    const char * s;
+    
+    uint16_t i;
+    
+    s = start;
+    i = 0;
+
+    while(*s)
+        i = i * 37 + *s++;
+
+    return i;
+}
+
+/*********************************************************************
+** Table
+*********************************************************************/
+
+void TableInit(TTable *t)
+{
+    t->item=NULL;
+    t->size=t->maxsize=0;
+}
+
+void TableFree(TTable *t)
+{
+    uint16_t i;
+
+    if (t->item)
+    {
+        if (t->size)
+            for (i=t->size;i>0;i--)
+            {
+                free(t->item[i-1].name);
+                free(t->item[i-1].value);
+            };
+            
+        free(t->item);
+    }
+
+    TableInit(t);
+}
+
+
+
+abyss_bool
+TableFindIndex(TTable *     const t,
+               const char * const name,
+               uint16_t *   const index) {
+
+    uint16_t i,hash=Hash16(name);
+
+    if ((t->item) && (t->size>0) && (*index<t->size))
+    {
+        for (i=*index;i<t->size;i++)
+            if (hash==t->item[i].hash)
+                if (strcmp(t->item[i].name,name)==0)
+                {
+                    *index=i;
+                    return TRUE;
+                };
+    };
+
+    return FALSE;
+}
+
+
+
+abyss_bool
+TableAddReplace(TTable *     const t,
+                const char * const name,
+                const char * const value) {
+
+    uint16_t i=0;
+
+    if (TableFindIndex(t,name,&i))
+    {
+        free(t->item[i].value);
+        if (value)
+            t->item[i].value=strdup(value);
+        else
+        {
+            free(t->item[i].name);
+            if (--t->size>0)
+                t->item[i]=t->item[t->size];
+        };
+
+        return TRUE;
+    }
+    else
+        return TableAdd(t,name,value);
+}
+
+
+
+abyss_bool
+TableAdd(TTable *     const t,
+         const char * const name,
+         const char * const value) {
+
+    if (t->size>=t->maxsize) {
+        TTableItem *newitem;
+        
+        t->maxsize+=16;
+
+        newitem=(TTableItem *)realloc(t->item,(t->maxsize)*sizeof(TTableItem));
+        if (newitem)
+            t->item=newitem;
+        else {
+            t->maxsize-=16;
+            return FALSE;
+        }
+    }
+
+    t->item[t->size].name=strdup(name);
+    t->item[t->size].value=strdup(value);
+    t->item[t->size].hash=Hash16(name);
+
+    ++t->size;
+
+    return TRUE;
+}
+
+
+
+char *
+TableFind(TTable *     const t,
+          const char * const name) {
+
+    uint16_t i=0;
+
+    if (TableFindIndex(t,name,&i))
+        return t->item[i].value;
+    else
+        return NULL;
+}
+
+/*********************************************************************
+** Pool
+*********************************************************************/
+
+static TPoolZone *
+PoolZoneAlloc(uint32_t const zonesize) {
+
+    TPoolZone * poolZoneP;
+    
+    MALLOCARRAY(poolZoneP, zonesize);
+    if (poolZoneP) {
+        poolZoneP->pos    = &poolZoneP->data[0];
+        poolZoneP->maxpos = poolZoneP->pos + zonesize;
+        poolZoneP->next   = NULL;
+        poolZoneP->prev   = NULL;
+    }
+    return poolZoneP;
+}
+
+
+
+static void
+PoolZoneFree(TPoolZone * const poolZoneP) {
+
+    free(poolZoneP);
+}
+
+
+
+abyss_bool
+PoolCreate(TPool *  const poolP,
+           uint32_t const zonesize) {
+
+    abyss_bool success;
+    abyss_bool mutexCreated;
+
+    poolP->zonesize = zonesize;
+
+    mutexCreated = MutexCreate(&poolP->mutex);
+    if (mutexCreated) {
+        TPoolZone * const firstZoneP = PoolZoneAlloc(zonesize);
+
+        if (firstZoneP != NULL) {
+            poolP->firstzone   = firstZoneP;
+            poolP->currentzone = firstZoneP;
+            success = TRUE;
+        } else
+            success = FALSE;
+        if (!success)
+            MutexFree(&poolP->mutex);
+    } else
+        success = FALSE;
+
+    return success;
+}
+
+
+
+void *
+PoolAlloc(TPool *  const poolP,
+          uint32_t const size) {
+/*----------------------------------------------------------------------------
+   Allocate a block of size 'size' from pool 'poolP'.
+-----------------------------------------------------------------------------*/
+    void * retval;
+
+    if (size == 0)
+        retval = NULL;
+    else {
+        abyss_bool gotMutexLock;
+
+        gotMutexLock = MutexLock(&poolP->mutex);
+        if (!gotMutexLock)
+            retval = NULL;
+        else {
+            TPoolZone * const curPoolZoneP = poolP->currentzone;
+
+            if (curPoolZoneP->pos + size < curPoolZoneP->maxpos) {
+                retval = curPoolZoneP->pos;
+                curPoolZoneP->pos += size;
+            } else {
+                uint32_t const zonesize = MAX(size, poolP->zonesize);
+
+                TPoolZone * const newPoolZoneP = PoolZoneAlloc(zonesize);
+                if (newPoolZoneP) {
+                    newPoolZoneP->prev = curPoolZoneP;
+                    newPoolZoneP->next = curPoolZoneP->next;
+                    curPoolZoneP->next = newPoolZoneP;
+                    poolP->currentzone = newPoolZoneP;
+                    retval= newPoolZoneP->data;
+                    newPoolZoneP->pos = newPoolZoneP->data + size;
+                } else
+                    retval = NULL;
+            }
+            MutexUnlock(&poolP->mutex);
+        }
+    }
+    return retval;
+}
+
+
+
+void
+PoolReturn(TPool *  const poolP,
+           void *   const blockP) {
+/*----------------------------------------------------------------------------
+   Return the block at 'blockP' to the pool 'poolP'.  WE ASSUME THAT IS
+   THE MOST RECENTLY ALLOCATED AND NOT RETURNED BLOCK IN THE POOL.
+-----------------------------------------------------------------------------*/
+    TPoolZone * const curPoolZoneP = poolP->currentzone;
+
+    assert((char*)curPoolZoneP->data < (char*)blockP &&
+           (char*)blockP < (char*)curPoolZoneP->pos);
+
+    curPoolZoneP->pos = blockP;
+
+    if (curPoolZoneP->pos == curPoolZoneP->data) {
+        /* That emptied out the current zone.  Free it and make the previous
+           zone current.
+        */
+
+        assert(curPoolZoneP->prev);  /* entry condition */
+
+        curPoolZoneP->prev->next = NULL;
+
+        PoolZoneFree(curPoolZoneP);
+    }
+}
+
+
+
+void
+PoolFree(TPool * const poolP) {
+
+    TPoolZone * poolZoneP;
+    TPoolZone * nextPoolZoneP;
+    
+    for (poolZoneP = poolP->firstzone; poolZoneP; poolZoneP = nextPoolZoneP) {
+        nextPoolZoneP = poolZoneP->next;
+        free(poolZoneP);
+    }
+}
+
+
+
+const char *
+PoolStrdup(TPool *      const poolP,
+           const char * const origString) {
+
+    char * newString;
+
+    if (origString == NULL)
+        newString = NULL;
+    else {
+        newString = PoolAlloc(poolP, strlen(origString) + 1);
+        if (newString != NULL)
+            strcpy(newString, origString);
+    }
+    return newString;
+}
diff --git a/lib/abyss/src/data.h b/lib/abyss/src/data.h
new file mode 100644 (file)
index 0000000..c990d99
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef DATA_H_INCLUDED
+#define DATA_H_INCLUDED
+
+#include "thread.h"
+
+/*********************************************************************
+** List
+*********************************************************************/
+
+typedef struct {
+    void **item;
+    uint16_t size;
+    uint16_t maxsize;
+    abyss_bool autofree;
+} TList;
+
+void
+ListInit(TList * const listP);
+
+void
+ListInitAutoFree(TList * const listP);
+
+void
+ListFree(TList * const listP);
+
+void
+ListFreeItems(TList * const listP);
+
+abyss_bool
+ListAdd(TList * const listP,
+        void *  const str);
+
+void
+ListRemove(TList * const listP);
+
+abyss_bool
+ListAddFromString(TList *      const listP,
+                  const char * const c);
+
+abyss_bool
+ListFindString(TList *      const listP,
+               const char * const str,
+               uint16_t *   const indexP);
+
+
+typedef struct 
+{
+    char *name,*value;
+    uint16_t hash;
+} TTableItem;
+
+typedef struct
+{
+    TTableItem *item;
+    uint16_t size,maxsize;
+} TTable;
+
+void
+TableInit(TTable * const t);
+
+void
+TableFree(TTable * const t);
+
+abyss_bool
+TableAdd(TTable *     const t,
+         const char * const name,
+         const char * const value);
+
+abyss_bool
+TableAddReplace(TTable *     const t,
+                const char * const name,
+                const char * const value);
+
+abyss_bool
+TableFindIndex(TTable *     const t,
+               const char * const name,
+               uint16_t *   const index);
+
+char *
+TableFind(TTable *     const t,
+          const char * const name);
+
+
+/*********************************************************************
+** Pool
+*********************************************************************/
+
+typedef struct _TPoolZone {
+    char * pos;
+    char * maxpos;
+    struct _TPoolZone * next;
+    struct _TPoolZone * prev;
+/*  char data[0]; Some compilers don't accept this */
+    char data[1];
+} TPoolZone;
+
+typedef struct {
+    TPoolZone * firstzone;
+    TPoolZone * currentzone;
+    uint32_t zonesize;
+    TMutex mutex;
+} TPool;
+
+abyss_bool
+PoolCreate(TPool *  const poolP,
+           uint32_t const zonesize);
+
+void
+PoolFree(TPool * const poolP);
+
+void *
+PoolAlloc(TPool *  const poolP,
+          uint32_t const size);
+
+void
+PoolReturn(TPool *  const poolP,
+           void *   const blockP);
+
+const char *
+PoolStrdup(TPool *      const poolP,
+           const char * const origString);
+
+
+#endif
diff --git a/lib/abyss/src/date.c b/lib/abyss/src/date.c
new file mode 100644 (file)
index 0000000..91c9fa7
--- /dev/null
@@ -0,0 +1,192 @@
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+
+
+#include <inttypes.h>
+#include "date.h"
+
+/*********************************************************************
+** Date
+*********************************************************************/
+
+static char *_DateDay[7]=
+{
+    "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
+};
+
+static char *_DateMonth[12]=
+{
+    "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+static int32_t _DateTimeBias=0;
+static char _DateTimeBiasStr[6]="";
+
+abyss_bool DateToString(TDate *tm,char *s)
+{
+    if (mktime(tm)==(time_t)(-1))
+    {
+        *s='\0';
+        return FALSE;
+    };
+
+    sprintf(s,"%s, %02d %s %04d %02d:%02d:%02d GMT",_DateDay[tm->tm_wday],tm->tm_mday,
+                _DateMonth[tm->tm_mon],tm->tm_year+1900,tm->tm_hour,tm->tm_min,tm->tm_sec);
+
+    return TRUE;
+}
+
+
+
+abyss_bool
+DateToLogString(TDate * const tmP,
+                char *  const s) {
+    time_t t;
+
+    t = mktime(tmP);
+    if (t != (time_t)(-1)) {
+        TDate d;
+        abyss_bool success;
+        success = DateFromLocal(&d, t);
+        if (success) {
+            sprintf(s, "%02d/%s/%04d:%02d:%02d:%02d %s",
+                    d.tm_mday, _DateMonth[d.tm_mon],
+                    d.tm_year+1900, d.tm_hour, d.tm_min, d.tm_sec,
+                    _DateTimeBiasStr);
+            return TRUE;
+        }
+    }
+    *s = '\0';
+    return FALSE;
+}
+
+
+
+abyss_bool
+DateDecode(const char *  const dateString,
+           TDate *       const tmP) {
+
+    int rc;
+    const char * s;
+    uint32_t n;
+
+    s = &dateString[0];
+
+    /* Ignore spaces, day name and spaces */
+    while ((*s==' ') || (*s=='\t'))
+        ++s;
+
+    while ((*s!=' ') && (*s!='\t'))
+        ++s;
+
+    while ((*s==' ') || (*s=='\t'))
+        ++s;
+
+    /* try to recognize the date format */
+    rc = sscanf(s, "%*s %d %d:%d:%d %d%*s", &tmP->tm_mday, &tmP->tm_hour,
+                &tmP->tm_min, &tmP->tm_sec, &tmP->tm_year);
+    if (rc != 5) {
+        int rc;
+        rc = sscanf(s, "%d %n%*s %d %d:%d:%d GMT%*s",
+                    &tmP->tm_mday,&n,&tmP->tm_year,
+                    &tmP->tm_hour, &tmP->tm_min, &tmP->tm_sec);
+        if (rc != 5) {
+            int rc;
+            rc = sscanf(s, "%d-%n%*[A-Za-z]-%d %d:%d:%d GMT%*s",
+                        &tmP->tm_mday, &n, &tmP->tm_year,
+                        &tmP->tm_hour, &tmP->tm_min, &tmP->tm_sec);
+            if (rc != 5)
+                return FALSE;
+        }
+    }    
+    /* s points now to the month string */
+    s += n;
+    for (n = 0; n < 12; ++n) {
+        char * p;
+
+        p =_DateMonth[n];
+
+        if (tolower(*p++) == tolower(*s))
+            if (*p++ == tolower(s[1]))
+                if (*p == tolower(s[2]))
+                    break;
+    }
+
+    if (n == 12)
+        return FALSE;
+
+    tmP->tm_mon = n;
+
+    /* finish the work */
+    if (tmP->tm_year > 1900)
+        tmP->tm_year -= 1900;
+    else {
+        if (tmP->tm_year < 70)
+            tmP->tm_year += 100;
+    }
+    tmP->tm_isdst = 0;
+
+    return (mktime(tmP) != (time_t)(-1));
+}
+
+
+
+int32_t DateCompare(TDate *d1,TDate *d2)
+{
+    int32_t x;
+
+    if ((x=d1->tm_year-d2->tm_year)==0)
+        if ((x=d1->tm_mon-d2->tm_mon)==0)
+            if ((x=d1->tm_mday-d2->tm_mday)==0)
+                if ((x=d1->tm_hour-d2->tm_hour)==0)
+                    if ((x=d1->tm_min-d2->tm_min)==0)
+                        x=d1->tm_sec-d2->tm_sec;
+
+    return x;
+}
+
+
+
+abyss_bool
+DateFromGMT(TDate *d,time_t t) {
+    TDate *dx;
+
+    dx=gmtime(&t);
+    if (dx) {
+        *d=*dx;
+        return TRUE;
+    };
+
+    return FALSE;
+}
+
+abyss_bool DateFromLocal(TDate *d,time_t t)
+{
+    return DateFromGMT(d,t+_DateTimeBias*2);
+}
+
+
+
+abyss_bool
+DateInit() {
+    time_t t;
+    TDate gmt,local,*d;
+
+    time(&t);
+    if (DateFromGMT(&gmt,t)) {
+        d=localtime(&t);
+        if (d) {
+            local=*d;
+            _DateTimeBias =
+                (local.tm_sec-gmt.tm_sec)+(local.tm_min-gmt.tm_min)*60
+                +(local.tm_hour-gmt.tm_hour)*3600;
+            sprintf(_DateTimeBiasStr, "%+03d%02d",
+                    _DateTimeBias/3600,(abs(_DateTimeBias) % 3600)/60);
+            return TRUE;
+        };
+    }
+    return FALSE;
+}
diff --git a/lib/abyss/src/date.h b/lib/abyss/src/date.h
new file mode 100644 (file)
index 0000000..4f407c0
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef DATE_H_INCLUDED
+#define DATE_H_INCLUDED
+
+#include <time.h>
+
+#include "xmlrpc-c/abyss.h"
+
+typedef struct tm TDate;
+
+abyss_bool
+DateToString(TDate * const tmP,
+             char *  const s);
+
+abyss_bool
+DateToLogString(TDate * const tmP,
+                char *  const s);
+
+abyss_bool
+DateDecode(const char *  const dateString,
+           TDate *       const tmP);
+
+int32_t
+DateCompare(TDate * const d1,
+            TDate * const d2);
+
+abyss_bool
+DateFromGMT(TDate * const d,
+            time_t  const t);
+
+abyss_bool
+DateFromLocal(TDate * const d,
+              time_t const t);
+
+#endif
diff --git a/lib/abyss/src/file.c b/lib/abyss/src/file.c
new file mode 100644 (file)
index 0000000..355bbc2
--- /dev/null
@@ -0,0 +1,244 @@
+/******************************************************************************
+**
+** file.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
+
+#include <string.h>
+
+#ifdef WIN32
+#include <io.h>
+#endif
+
+#ifndef WIN32
+#include <dirent.h>
+#include <sys/stat.h>
+#endif
+
+#include "xmlrpc-c/abyss.h"
+#include "file.h"
+
+/*********************************************************************
+** File
+*********************************************************************/
+
+abyss_bool FileOpen(TFile *f, const char *name,uint32_t attrib)
+{
+#if defined( WIN32 ) && !defined( __BORLANDC__ )
+    return ((*f=_open(name,attrib))!=(-1));
+#else
+    return ((*f=open(name,attrib))!=(-1));
+#endif
+}
+
+abyss_bool FileOpenCreate(TFile *f, const char *name, uint32_t attrib)
+{
+#if defined( WIN32 ) && !defined( __BORLANDC__ )
+    return ((*f=_open(name,attrib | O_CREAT,_S_IWRITE | _S_IREAD))!=(-1));
+#else
+    return ((*f=open(name,attrib | O_CREAT,S_IWRITE | S_IREAD))!=(-1));
+#endif
+}
+
+abyss_bool
+FileWrite(TFile *      const f,
+          const void * const buffer,
+          uint32_t     const len) {
+#if defined( WIN32 ) && !defined( __BORLANDC__ )
+    return (_write(*f,buffer,len)==(int32_t)len);
+#else
+    return (write(*f,buffer,len)==(int32_t)len);
+#endif
+}
+
+int32_t FileRead(TFile *f, void *buffer, uint32_t len)
+{
+#if defined( WIN32 ) && !defined( __BORLANDC__ )
+    return (_read(*f,buffer,len));
+#else
+    return (read(*f,buffer,len));
+#endif
+}
+
+abyss_bool FileSeek(TFile *f, uint64_t pos, uint32_t attrib)
+{
+#if defined( WIN32 ) && !defined( __BORLANDC__ )
+    return (_lseek(*f,pos,attrib)!=(-1));
+#else
+    return (lseek(*f,pos,attrib)!=(-1));
+#endif
+}
+
+uint64_t FileSize(TFile *f)
+{
+#if defined( WIN32 ) && !defined( __BORLANDC__ )
+    return (_filelength(*f));
+#else
+    struct stat fs;
+
+    fstat(*f,&fs);
+    return (fs.st_size);
+#endif  
+}
+
+abyss_bool FileClose(TFile *f)
+{
+#if defined( WIN32 ) && !defined( __BORLANDC__ )
+    return (_close(*f)!=(-1));
+#else
+    return (close(*f)!=(-1));
+#endif
+}
+
+
+
+abyss_bool
+FileStat(const char * const filename,
+         TFileStat *  const filestat) {
+#if defined( WIN32 ) && !defined( __BORLANDC__ )
+    return (_stati64(filename,filestat)!=(-1));
+#else
+    return (stat(filename,filestat)!=(-1));
+#endif
+}
+
+
+
+abyss_bool
+FileFindFirst(TFileFind *  const filefind,
+              const char * const path,
+              TFileInfo *  const fileinfo) {
+#ifdef WIN32
+    abyss_bool ret;
+    char *p=path+strlen(path);
+
+    *p='\\';
+    *(p+1)='*';
+    *(p+2)='\0';
+#ifndef __BORLANDC__
+    ret=(((*filefind)=_findfirst(path,fileinfo))!=(-1));
+#else
+    *filefind = FindFirstFile( path, &fileinfo->data );
+   ret = *filefind != NULL;
+   if( ret )
+   {
+      LARGE_INTEGER li;
+      li.LowPart = fileinfo->data.nFileSizeLow;
+      li.HighPart = fileinfo->data.nFileSizeHigh;
+      strcpy( fileinfo->name, fileinfo->data.cFileName );
+       fileinfo->attrib = fileinfo->data.dwFileAttributes;
+       fileinfo->size   = li.QuadPart;
+      fileinfo->time_write = fileinfo->data.ftLastWriteTime.dwLowDateTime;
+   }
+#endif
+    *p='\0';
+    return ret;
+#else  /* WIN32 */
+    strncpy(filefind->path,path,NAME_MAX);
+    filefind->path[NAME_MAX]='\0';
+    filefind->handle=opendir(path);
+    if (filefind->handle)
+        return FileFindNext(filefind,fileinfo);
+
+    return FALSE;
+#endif /* WIN32 */
+}
+
+
+
+abyss_bool FileFindNext(TFileFind *filefind,TFileInfo *fileinfo)
+{
+#ifdef WIN32
+
+#ifndef __BORLANDC__
+    return (_findnext(*filefind,fileinfo)!=(-1));
+#else
+   abyss_bool ret = FindNextFile( *filefind, &fileinfo->data );
+   if( ret )
+   {
+      LARGE_INTEGER li;
+      li.LowPart = fileinfo->data.nFileSizeLow;
+      li.HighPart = fileinfo->data.nFileSizeHigh;
+      strcpy( fileinfo->name, fileinfo->data.cFileName );
+       fileinfo->attrib = fileinfo->data.dwFileAttributes;
+       fileinfo->size   = li.QuadPart;
+      fileinfo->time_write = fileinfo->data.ftLastWriteTime.dwLowDateTime;
+   }
+    return ret;
+#endif
+
+#else  /* WIN32 */
+    struct dirent *de;
+    /****** Must be changed ***/
+    char z[NAME_MAX+1];
+
+    de=readdir(filefind->handle);
+    if (de)
+    {
+        struct stat fs;
+
+        strcpy(fileinfo->name,de->d_name);
+        strcpy(z,filefind->path);
+        strncat(z,"/",NAME_MAX);
+        strncat(z,fileinfo->name,NAME_MAX);
+        z[NAME_MAX]='\0';
+        
+        stat(z,&fs);
+
+        if (fs.st_mode & S_IFDIR)
+            fileinfo->attrib=A_SUBDIR;
+        else
+            fileinfo->attrib=0;
+
+        fileinfo->size=fs.st_size;
+        fileinfo->time_write=fs.st_mtime;
+        
+        return TRUE;
+    };
+
+    return FALSE;
+#endif /* WIN32 */
+}
+
+void FileFindClose(TFileFind *filefind)
+{
+#ifdef WIN32
+
+#ifndef __BORLANDC__
+    _findclose(*filefind);
+#else
+   FindClose( *filefind );
+#endif
+
+#else  /* WIN32 */
+    closedir(filefind->handle);
+#endif /* WIN32 */
+}
diff --git a/lib/abyss/src/file.h b/lib/abyss/src/file.h
new file mode 100644 (file)
index 0000000..c7cefbd
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef FILE_H_INCLUDED
+#define FILE_H_INCLUDED
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+
+#include "xmlrpc-c/abyss.h"
+
+#ifndef NAME_MAX
+#define NAME_MAX    1024
+#endif
+
+#ifdef WIN32
+#ifndef __BORLANDC__
+#define O_APPEND    _O_APPEND
+#define O_CREAT     _O_CREAT 
+#define O_EXCL      _O_EXCL
+#define O_RDONLY    _O_RDONLY
+#define O_RDWR      _O_RDWR 
+#define O_TRUNC _O_TRUNC
+#define O_WRONLY    _O_WRONLY
+#define O_TEXT      _O_TEXT
+#define O_BINARY    _O_BINARY
+#endif
+
+#define A_HIDDEN    _A_HIDDEN
+#define A_NORMAL    _A_NORMAL
+#define A_RDONLY    _A_RDONLY
+#define A_SUBDIR    _A_SUBDIR
+#else
+#define A_SUBDIR    1
+#define O_BINARY    0
+#define O_TEXT      0
+#endif  /* WIN32 */
+
+#ifdef WIN32
+
+#ifndef __BORLANDC__
+typedef struct _stati64 TFileStat;
+typedef struct _finddata_t TFileInfo;
+typedef long TFileFind;
+
+#else  /* WIN32 */
+
+typedef struct stat TFileStat;
+typedef struct finddata_t {
+    char name[NAME_MAX+1];
+    int attrib;
+    uint64_t size;
+    time_t time_write;
+    WIN32_FIND_DATA data;
+} TFileInfo;
+
+typedef HANDLE TFileFind;
+
+#endif /* WIN32 */
+
+#else
+
+#include <unistd.h>
+#include <dirent.h>
+
+typedef struct stat TFileStat;
+
+typedef struct finddata_t {
+    char name[NAME_MAX+1];
+    int attrib;
+    uint64_t size;
+    time_t time_write;
+} TFileInfo;
+
+typedef struct {
+    char path[NAME_MAX+1];
+    DIR *handle;
+} TFileFind;
+
+#endif
+
+typedef int TFile;
+
+abyss_bool
+FileOpen(TFile *      const f,
+         const char * const name,
+         uint32_t     const attrib);
+
+abyss_bool
+FileOpenCreate(TFile *      const f,
+               const char * const name,
+               uint32_t     const attrib);
+
+abyss_bool
+FileClose(TFile * const f);
+
+abyss_bool
+FileWrite(TFile *      const f,
+          const void * const buffer,
+          uint32_t     const len);
+
+int32_t
+FileRead(TFile *  const f,
+         void *   const buffer,
+         uint32_t const len);
+
+abyss_bool
+FileSeek(TFile *  const f,
+         uint64_t const pos,
+         uint32_t const attrib);
+
+uint64_t
+FileSize(TFile * const f);
+
+abyss_bool
+FileStat(const char * const filename,
+         TFileStat *  const filestat);
+
+abyss_bool
+FileFindFirst(TFileFind *  const filefind,
+              const char * const path,
+              TFileInfo *  const fileinfo);
+
+abyss_bool
+FileFindNext(TFileFind * const filefind,
+             TFileInfo * const fileinfo);
+
+void
+FileFindClose(TFileFind * const filefind);
+
+#endif
diff --git a/lib/abyss/src/http.c b/lib/abyss/src/http.c
new file mode 100644 (file)
index 0000000..bbd9a0e
--- /dev/null
@@ -0,0 +1,857 @@
+/* Copyright information is at the end of the file */
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include "xmlrpc_config.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "server.h"
+#include "session.h"
+#include "conn.h"
+#include "token.h"
+#include "date.h"
+#include "data.h"
+#include "abyss_info.h"
+
+#include "http.h"
+
+/*********************************************************************
+** Request Parser
+*********************************************************************/
+
+/*********************************************************************
+** Request
+*********************************************************************/
+
+static void
+initRequestInfo(TRequestInfo * const requestInfoP,
+                httpVersion    const httpVersion,
+                const char *   const requestLine,
+                TMethod        const httpMethod,
+                const char *   const host,
+                unsigned int   const port,
+                const char *   const path,
+                const char *   const query) {
+/*----------------------------------------------------------------------------
+  Set up the request info structure.  For information that is
+  controlled by headers, use the defaults -- I.e. the value that
+  applies if the request contains no applicable header.
+-----------------------------------------------------------------------------*/
+    requestInfoP->requestline = requestLine;
+    requestInfoP->method      = httpMethod;
+    requestInfoP->host        = host;
+    requestInfoP->port        = port;
+    requestInfoP->uri         = path;
+    requestInfoP->query       = query;
+    requestInfoP->from        = NULL;
+    requestInfoP->useragent   = NULL;
+    requestInfoP->referer     = NULL;
+    requestInfoP->user        = NULL;
+
+    if (httpVersion.major > 1 ||
+        (httpVersion.major == 1 && httpVersion.minor >= 1))
+        requestInfoP->keepalive = TRUE;
+    else
+        requestInfoP->keepalive = FALSE;
+}
+
+
+
+static void
+freeRequestInfo(TRequestInfo * const requestInfoP) {
+
+    if (requestInfoP->requestline)
+        xmlrpc_strfree(requestInfoP->requestline);
+
+    if (requestInfoP->user)
+        xmlrpc_strfree(requestInfoP->user);
+}
+
+
+
+void
+RequestInit(TSession * const sessionP,
+            TConn *    const connectionP) {
+
+    time_t nowtime;
+
+    sessionP->validRequest = false;  /* Don't have valid request yet */
+
+    time(&nowtime);
+    sessionP->date = *gmtime(&nowtime);
+
+    sessionP->conn = connectionP;
+
+    sessionP->responseStarted = FALSE;
+
+    sessionP->chunkedwrite = FALSE;
+    sessionP->chunkedwritemode = FALSE;
+
+    sessionP->continueRequired = FALSE;
+
+    ListInit(&sessionP->cookies);
+    ListInit(&sessionP->ranges);
+    TableInit(&sessionP->request_headers);
+    TableInit(&sessionP->response_headers);
+
+    sessionP->status = 0;  /* No status from handler yet */
+
+    StringAlloc(&(sessionP->header));
+}
+
+
+
+void
+RequestFree(TSession * const sessionP) {
+
+    if (sessionP->validRequest)
+        freeRequestInfo(&sessionP->request_info);
+
+    ListFree(&sessionP->cookies);
+    ListFree(&sessionP->ranges);
+    TableFree(&sessionP->request_headers);
+    TableFree(&sessionP->response_headers);
+    StringFree(&(sessionP->header));
+}
+
+
+
+static void
+readRequestLine(TSession *   const sessionP,
+                char **      const requestLineP,
+                uint16_t *   const httpErrorCodeP) {
+
+    *httpErrorCodeP = 0;
+
+    /* Ignore CRLFs in the beginning of the request (RFC2068-P30) */
+    do {
+        abyss_bool success;
+        success = ConnReadHeader(sessionP->conn, requestLineP);
+        if (!success)
+            *httpErrorCodeP = 408;  /* Request Timeout */
+    } while (!*httpErrorCodeP && (*requestLineP)[0] == '\0');
+}
+
+
+
+static void
+unescapeUri(char *       const uri,
+            abyss_bool * const errorP) {
+
+    char * x;
+    char * y;
+
+    x = y = uri;
+    
+    *errorP = FALSE;
+
+    while (*x && !*errorP) {
+        switch (*x) {
+        case '%': {
+            char c;
+            ++x;
+            c = tolower(*x++);
+            if ((c >= '0') && (c <= '9'))
+                c -= '0';
+            else if ((c >= 'a') && (c <= 'f'))
+                c -= 'a' - 10;
+            else
+                *errorP = TRUE;
+
+            if (!*errorP) {
+                char d;
+                d = tolower(*x++);
+                if ((d >= '0') && (d <= '9'))
+                    d -= '0';
+                else if ((d >= 'a') && (d <= 'f'))
+                    d -= 'a' - 10;
+                else
+                    *errorP = TRUE;
+
+                if (!*errorP)
+                    *y++ = ((c << 4) | d);
+            }
+        } break;
+
+        default:
+            *y++ = *x++;
+            break;
+        }
+    }
+    *y = '\0';
+}
+
+
+
+static void
+parseHostPort(char *           const hostport,
+              const char **    const hostP,
+              unsigned short * const portP,
+              uint16_t *       const httpErrorCodeP) {
+    
+    char * colonPos;
+
+    colonPos = strchr(hostport, ':');
+    if (colonPos) {
+        const char * p;
+        uint32_t port;
+
+        *colonPos = '\0';  /* Split hostport at the colon */
+
+        *hostP = hostport;
+
+        for (p = colonPos + 1, port = 0;
+             isdigit(*p) && port < 65535;
+             (port = port * 10 + (*p - '0')), ++p);
+            
+        *portP = port;
+
+        if (*p || port == 0)
+            *httpErrorCodeP = 400;  /* Bad Request */
+        else
+            *httpErrorCodeP = 0;
+    } else {
+        *hostP          = hostport;
+        *portP          = 80;
+        *httpErrorCodeP = 0;
+    }
+}
+
+
+
+static void
+parseRequestUri(char *           const requestUri,
+                const char **    const hostP,
+                const char **    const pathP,
+                const char **    const queryP,
+                unsigned short * const portP,
+                uint16_t *       const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+  Parse the request URI (in the request line
+  "GET http://www.myserver.com/myfile?parm HTTP/1.1",
+  "http://www.myserver.com/myfile?parm" is the request URI).
+
+  This destroys *requestUri and returns pointers into *requestUri!
+
+  This is extremely ugly.  We need to redo it with dynamically allocated
+  storage.  We should return individual malloc'ed strings.
+-----------------------------------------------------------------------------*/
+    abyss_bool error;
+
+    unescapeUri(requestUri, &error);
+    
+    if (error)
+        *httpErrorCodeP = 400;  /* Bad Request */
+    else {
+        char * requestUriNoQuery;
+           /* The request URI with any query (the stuff marked by a question
+              mark at the end of a request URI) chopped off.
+           */
+        {
+            /* Split requestUri at the question mark */
+            char * const qmark = strchr(requestUri, '?');
+            
+            if (qmark) {
+                *qmark = '\0';
+                *queryP = qmark + 1;
+            } else
+                *queryP = NULL;
+        }
+        
+        requestUriNoQuery = requestUri;
+
+        if (requestUriNoQuery[0] == '/') {
+            *hostP = NULL;
+            *pathP = requestUriNoQuery;
+            *portP = 80;
+        } else {
+            if (!xmlrpc_strneq(requestUriNoQuery, "http://", 7))
+                *httpErrorCodeP = 400;  /* Bad Request */
+            else {
+                char * const hostportpath = &requestUriNoQuery[7];
+                char * const slashPos = strchr(hostportpath, '/');
+                char * hostport;
+                
+                if (slashPos) {
+                    char * p;
+                    *pathP = slashPos;
+                    
+                    /* Nul-terminate the host name.  To make space for
+                       it, slide the whole name back one character.
+                       This moves it into the space now occupied by
+                       the end of "http://", which we don't need.
+                    */
+                    for (p = hostportpath; *p != '/'; ++p)
+                        *(p-1) = *p;
+                    *(p-1) = '\0';
+                    
+                    hostport = hostportpath - 1;
+                    *httpErrorCodeP = 0;
+                } else {
+                    *pathP = "*";
+                    hostport = hostportpath;
+                    *httpErrorCodeP = 0;
+                }
+                if (!*httpErrorCodeP)
+                    parseHostPort(hostport, hostP, portP, httpErrorCodeP);
+            }
+        }
+    }
+}
+
+
+
+static void
+parseRequestLine(char *           const requestLine,
+                 TMethod *        const httpMethodP,
+                 httpVersion *    const httpVersionP,
+                 const char **    const hostP,
+                 unsigned short * const portP,
+                 const char **    const pathP,
+                 const char **    const queryP,
+                 abyss_bool *     const moreLinesP,
+                 uint16_t *       const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+   Modifies *header1 and returns pointers to its storage!
+-----------------------------------------------------------------------------*/
+    const char * httpMethodName;
+    char * p;
+
+    p = requestLine;
+
+    /* Jump over spaces */
+    NextToken((const char **)&p);
+
+    httpMethodName = GetToken(&p);
+    if (!httpMethodName)
+        *httpErrorCodeP = 400;  /* Bad Request */
+    else {
+        char * requestUri;
+
+        if (xmlrpc_streq(httpMethodName, "GET"))
+            *httpMethodP = m_get;
+        else if (xmlrpc_streq(httpMethodName, "PUT"))
+            *httpMethodP = m_put;
+        else if (xmlrpc_streq(httpMethodName, "OPTIONS"))
+            *httpMethodP = m_options;
+        else if (xmlrpc_streq(httpMethodName, "DELETE"))
+            *httpMethodP = m_delete;
+        else if (xmlrpc_streq(httpMethodName, "POST"))
+            *httpMethodP = m_post;
+        else if (xmlrpc_streq(httpMethodName, "TRACE"))
+            *httpMethodP = m_trace;
+        else if (xmlrpc_streq(httpMethodName, "HEAD"))
+            *httpMethodP = m_head;
+        else
+            *httpMethodP = m_unknown;
+        
+        /* URI and Query Decoding */
+        NextToken((const char **)&p);
+
+        
+        requestUri = GetToken(&p);
+        if (!requestUri)
+            *httpErrorCodeP = 400;  /* Bad Request */
+        else {
+            parseRequestUri(requestUri, hostP, pathP, queryP, portP,
+                            httpErrorCodeP);
+
+            if (!*httpErrorCodeP) {
+                const char * httpVersion;
+
+                NextToken((const char **)&p);
+        
+                /* HTTP Version Decoding */
+                
+                httpVersion = GetToken(&p);
+                if (httpVersion) {
+                    uint32_t vmin, vmaj;
+                    if (sscanf(httpVersion, "HTTP/%d.%d", &vmaj, &vmin) != 2)
+                        *httpErrorCodeP = 400;  /* Bad Request */
+                    else {
+                        httpVersionP->major = vmaj;
+                        httpVersionP->minor = vmin;
+                        *httpErrorCodeP = 0;  /* no error */
+                    }
+                    *moreLinesP = TRUE;
+                } else {
+                    /* There is no HTTP version, so this is a single
+                       line request.
+                    */
+                    *httpErrorCodeP = 0;  /* no error */
+                    *moreLinesP = FALSE;
+                }
+            }
+        }
+    }
+}
+
+
+
+static void
+strtolower(char * const s) {
+
+    char * t;
+
+    t = &s[0];
+    while (*t) {
+        *t = tolower(*t);
+        ++t;
+    }
+}
+
+
+
+static void
+getFieldNameToken(char **    const pP,
+                  char **    const fieldNameP,
+                  uint16_t * const httpErrorCodeP) {
+    
+    char * fieldName;
+
+    NextToken((const char **)pP);
+    
+    fieldName = GetToken(pP);
+    if (!fieldName)
+        *httpErrorCodeP = 400;  /* Bad Request */
+    else {
+        if (fieldName[strlen(fieldName)-1] != ':')
+            /* Not a valid field name */
+            *httpErrorCodeP = 400;  /* Bad Request */
+        else {
+            fieldName[strlen(fieldName)-1] = '\0';  /* remove trailing colon */
+
+            strtolower(fieldName);
+            
+            *httpErrorCodeP = 0;  /* no error */
+            *fieldNameP = fieldName;
+        }
+    }
+}
+
+
+
+static void
+processHeader(const char * const fieldName,
+              char *       const fieldValue,
+              TSession *   const sessionP,
+              uint16_t *   const httpErrorCodeP) {
+/*----------------------------------------------------------------------------
+   We may modify *fieldValue, and we put pointers to *fieldValue and
+   *fieldName into *sessionP.
+
+   We must fix this some day.  *sessionP should point to individual
+   malloc'ed strings.
+-----------------------------------------------------------------------------*/
+    *httpErrorCodeP = 0;  /* initial assumption */
+
+    if (xmlrpc_streq(fieldName, "connection")) {
+        if (xmlrpc_strcaseeq(fieldValue, "keep-alive"))
+            sessionP->request_info.keepalive = TRUE;
+        else
+            sessionP->request_info.keepalive = FALSE;
+    } else if (xmlrpc_streq(fieldName, "host"))
+        parseHostPort(fieldValue, &sessionP->request_info.host,
+                      &sessionP->request_info.port, httpErrorCodeP);
+    else if (xmlrpc_streq(fieldName, "from"))
+        sessionP->request_info.from = fieldValue;
+    else if (xmlrpc_streq(fieldName, "user-agent"))
+        sessionP->request_info.useragent = fieldValue;
+    else if (xmlrpc_streq(fieldName, "referer"))
+        sessionP->request_info.referer = fieldValue;
+    else if (xmlrpc_streq(fieldName, "range")) {
+        if (xmlrpc_strneq(fieldValue, "bytes=", 6)) {
+            abyss_bool succeeded;
+            succeeded = ListAddFromString(&sessionP->ranges, &fieldValue[6]);
+            *httpErrorCodeP = succeeded ? 0 : 400;
+        }
+    } else if (xmlrpc_streq(fieldName, "cookies")) {
+        abyss_bool succeeded;
+        succeeded = ListAddFromString(&sessionP->cookies, fieldValue);
+        *httpErrorCodeP = succeeded ? 0 : 400;
+    } else if (xmlrpc_streq(fieldName, "expect")) {
+        if (xmlrpc_strcaseeq(fieldValue, "100-continue"))
+            sessionP->continueRequired = TRUE;
+    }
+}
+
+
+
+abyss_bool
+RequestRead(TSession * const sessionP) {
+    uint16_t httpErrorCode;  /* zero for no error */
+    char * requestLine;
+
+    readRequestLine(sessionP, &requestLine, &httpErrorCode);
+    if (!httpErrorCode) {
+        TMethod httpMethod;
+        const char * host;
+        const char * path;
+        const char * query;
+        unsigned short port;
+        abyss_bool moreHeaders;
+
+        parseRequestLine(requestLine, &httpMethod, &sessionP->version,
+                         &host, &port, &path, &query,
+                         &moreHeaders, &httpErrorCode);
+
+        if (!httpErrorCode)
+            initRequestInfo(&sessionP->request_info, sessionP->version,
+                            strdup(requestLine),
+                            httpMethod, host, port, path, query);
+
+        while (moreHeaders && !httpErrorCode) {
+            char * p;
+            abyss_bool succeeded;
+            succeeded = ConnReadHeader(sessionP->conn, &p);
+            if (!succeeded)
+                httpErrorCode = 408;  /* Request Timeout */
+            else {
+                if (!*p)
+                    /* We have reached the empty line so all the request
+                       was read.
+                    */
+                    moreHeaders = FALSE;
+                else {
+                    char * fieldName;
+                    getFieldNameToken(&p, &fieldName, &httpErrorCode);
+                    if (!httpErrorCode) {
+                        char * fieldValue;
+
+                        NextToken((const char **)&p);
+                        
+                        fieldValue = p;
+                        
+                        TableAdd(&sessionP->request_headers,
+                                 fieldName, fieldValue);
+                        
+                        processHeader(fieldName, fieldValue, sessionP,
+                                      &httpErrorCode);
+                    }
+                }
+            }
+        }
+    }
+    if (httpErrorCode)
+        ResponseStatus(sessionP, httpErrorCode);
+    else
+        sessionP->validRequest = true;
+
+    return !httpErrorCode;
+}
+
+
+
+char *RequestHeaderValue(TSession *r,char *name)
+{
+    return (TableFind(&r->request_headers,name));
+}
+
+
+
+abyss_bool
+RequestValidURI(TSession * const sessionP) {
+
+    if (!sessionP->request_info.uri)
+        return FALSE;
+    
+    if (xmlrpc_streq(sessionP->request_info.uri, "*"))
+        return (sessionP->request_info.method != m_options);
+
+    if (strchr(sessionP->request_info.uri, '*'))
+        return FALSE;
+
+    return TRUE;
+}
+
+
+
+abyss_bool
+RequestValidURIPath(TSession * const sessionP) {
+
+    uint32_t i;
+    const char * p;
+
+    p = sessionP->request_info.uri;
+
+    i = 0;
+
+    if (*p == '/') {
+        i = 1;
+        while (*p)
+            if (*(p++) == '/') {
+                if (*p == '/')
+                    break;
+                else if ((strncmp(p,"./",2) == 0) || (strcmp(p, ".") == 0))
+                    ++p;
+                else if ((strncmp(p, "../", 2) == 0) ||
+                         (strcmp(p, "..") == 0)) {
+                    p += 2;
+                    --i;
+                    if (i == 0)
+                        break;
+                }
+                /* Prevent accessing hidden files (starting with .) */
+                else if (*p == '.')
+                    return FALSE;
+                else
+                    if (*p)
+                        ++i;
+            }
+    }
+    return (*p == 0 && i > 0);
+}
+
+
+
+abyss_bool
+RequestAuth(TSession *r,char *credential,char *user,char *pass) {
+
+    char *p,*x;
+    char z[80],t[80];
+
+    p=RequestHeaderValue(r,"authorization");
+    if (p) {
+        NextToken((const char **)&p);
+        x=GetToken(&p);
+        if (x) {
+            if (strcasecmp(x,"basic")==0) {
+                NextToken((const char **)&p);
+                sprintf(z,"%s:%s",user,pass);
+                Base64Encode(z,t);
+
+                if (strcmp(p,t)==0) {
+                    r->request_info.user=strdup(user);
+                    return TRUE;
+                };
+            };
+        }
+    };
+
+    sprintf(z,"Basic realm=\"%s\"",credential);
+    ResponseAddField(r,"WWW-Authenticate",z);
+    ResponseStatus(r,401);
+    return FALSE;
+}
+
+
+
+/*********************************************************************
+** Range
+*********************************************************************/
+
+abyss_bool RangeDecode(char *str,uint64_t filesize,uint64_t *start,uint64_t *end)
+{
+    char *ss;
+
+    *start=0;
+    *end=filesize-1;
+
+    if (*str=='-')
+    {
+        *start=filesize-strtol(str+1,&ss,10);
+        return ((ss!=str) && (!*ss));
+    };
+
+    *start=strtol(str,&ss,10);
+
+    if ((ss==str) || (*ss!='-'))
+        return FALSE;
+
+    str=ss+1;
+
+    if (!*str)
+        return TRUE;
+
+    *end=strtol(str,&ss,10);
+
+    if ((ss==str) || (*ss) || (*end<*start))
+        return FALSE;
+
+    return TRUE;
+}
+
+/*********************************************************************
+** HTTP
+*********************************************************************/
+
+const char *
+HTTPReasonByStatus(uint16_t const code) {
+
+    struct _HTTPReasons {
+        uint16_t status;
+        const char * reason;
+    };
+
+    static struct _HTTPReasons const reasons[] =  {
+        { 100,"Continue" }, 
+        { 101,"Switching Protocols" }, 
+        { 200,"OK" }, 
+        { 201,"Created" }, 
+        { 202,"Accepted" }, 
+        { 203,"Non-Authoritative Information" }, 
+        { 204,"No Content" }, 
+        { 205,"Reset Content" }, 
+        { 206,"Partial Content" }, 
+        { 300,"Multiple Choices" }, 
+        { 301,"Moved Permanently" }, 
+        { 302,"Moved Temporarily" }, 
+        { 303,"See Other" }, 
+        { 304,"Not Modified" }, 
+        { 305,"Use Proxy" }, 
+        { 400,"Bad Request" }, 
+        { 401,"Unauthorized" }, 
+        { 402,"Payment Required" }, 
+        { 403,"Forbidden" }, 
+        { 404,"Not Found" }, 
+        { 405,"Method Not Allowed" }, 
+        { 406,"Not Acceptable" }, 
+        { 407,"Proxy Authentication Required" }, 
+        { 408,"Request Timeout" }, 
+        { 409,"Conflict" }, 
+        { 410,"Gone" }, 
+        { 411,"Length Required" }, 
+        { 412,"Precondition Failed" }, 
+        { 413,"Request Entity Too Large" }, 
+        { 414,"Request-URI Too Long" }, 
+        { 415,"Unsupported Media Type" }, 
+        { 500,"Internal Server Error" }, 
+        { 501,"Not Implemented" }, 
+        { 502,"Bad Gateway" }, 
+        { 503,"Service Unavailable" }, 
+        { 504,"Gateway Timeout" }, 
+        { 505,"HTTP Version Not Supported" },
+        { 000, NULL }
+    };
+    const struct _HTTPReasons * reasonP;
+
+    reasonP = &reasons[0];
+
+    while (reasonP->status <= code)
+        if (reasonP->status == code)
+            return reasonP->reason;
+        else
+            ++reasonP;
+
+    return "No Reason";
+}
+
+
+
+int32_t
+HTTPRead(TSession *   const s ATTR_UNUSED,
+         const char * const buffer ATTR_UNUSED,
+         uint32_t     const len ATTR_UNUSED) {
+
+    return 0;
+}
+
+
+
+abyss_bool
+HTTPWriteBodyChunk(TSession *   const sessionP,
+                   const char * const buffer,
+                   uint32_t     const len) {
+
+    abyss_bool succeeded;
+
+    if (sessionP->chunkedwrite && sessionP->chunkedwritemode) {
+        char chunkHeader[16];
+
+        sprintf(chunkHeader, "%x\r\n", len);
+
+        succeeded =
+            ConnWrite(sessionP->conn, chunkHeader, strlen(chunkHeader));
+        if (succeeded) {
+            succeeded = ConnWrite(sessionP->conn, buffer, len);
+            if (succeeded)
+                succeeded = ConnWrite(sessionP->conn, "\r\n", 2);
+        }
+    } else
+        succeeded = ConnWrite(sessionP->conn, buffer, len);
+
+    return succeeded;
+}
+
+
+
+abyss_bool
+HTTPWriteEndChunk(TSession * const sessionP) {
+
+    abyss_bool retval;
+
+    if (sessionP->chunkedwritemode && sessionP->chunkedwrite) {
+        /* May be one day trailer dumping will be added */
+        sessionP->chunkedwritemode = FALSE;
+        retval = ConnWrite(sessionP->conn, "0\r\n\r\n", 5);
+    } else
+        retval = TRUE;
+
+    return retval;
+}
+
+
+
+abyss_bool
+HTTPKeepalive(TSession * const sessionP) {
+/*----------------------------------------------------------------------------
+   Return value: the connection should be kept alive after the session
+   *sessionP is over.
+-----------------------------------------------------------------------------*/
+    return (sessionP->request_info.keepalive &&
+            !sessionP->serverDeniesKeepalive &&
+            sessionP->status < 400);
+}
+
+
+
+abyss_bool
+HTTPWriteContinue(TSession * const sessionP) {
+
+    char const continueStatus[] = "HTTP/1.1 100 continue\r\n\r\n";
+        /* This is a status line plus an end-of-headers empty line */
+
+    return ConnWrite(sessionP->conn, continueStatus, strlen(continueStatus));
+}
+
+
+
+/******************************************************************************
+**
+** http.c
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
diff --git a/lib/abyss/src/http.h b/lib/abyss/src/http.h
new file mode 100644 (file)
index 0000000..2c6d6a4
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef HTTP_H_INCLUDED
+#define HTTP_H_INCLUDED
+
+#include "conn.h"
+
+/*********************************************************************
+** Request
+*********************************************************************/
+
+abyss_bool RequestValidURI(TSession *r);
+abyss_bool RequestValidURIPath(TSession *r);
+abyss_bool RequestUnescapeURI(TSession *r);
+
+abyss_bool RequestRead(TSession *r);
+void RequestInit(TSession *r,TConn *c);
+void RequestFree(TSession *r);
+
+abyss_bool RequestAuth(TSession *r,char *credential,char *user,char *pass);
+
+/*********************************************************************
+** HTTP
+*********************************************************************/
+
+const char *
+HTTPReasonByStatus(uint16_t const code);
+
+int32_t
+HTTPRead(TSession *   const sessionP,
+         const char * const buffer,
+         uint32_t     const len);
+
+abyss_bool
+HTTPWriteBodyChunk(TSession *   const sessionP,
+                   const char * const buffer,
+                   uint32_t     const len);
+
+abyss_bool
+HTTPWriteEndChunk(TSession * const sessionP);
+
+abyss_bool
+HTTPKeepalive(TSession * const sessionP);
+
+abyss_bool
+HTTPWriteContinue(TSession * const sessionP);
+
+#endif
diff --git a/lib/abyss/src/main.c b/lib/abyss/src/main.c
new file mode 100644 (file)
index 0000000..93bf966
--- /dev/null
@@ -0,0 +1,243 @@
+/******************************************************************************
+**
+** main.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+
+#ifdef WIN32
+#include <io.h>
+#endif  /* WIN32 */
+
+#ifdef _UNIX
+#include <sys/signal.h>
+#include <sys/wait.h>
+#endif
+
+#include "xmlrpc-c/abyss.h"
+
+void Answer(TSession *r, uint16_t statuscode, char *buffer)
+{
+    ResponseChunked(r);
+
+    ResponseStatus(r,statuscode);
+
+    ResponseContentType(r,"text/html");
+
+    ResponseWrite(r);
+    
+    HTTPWrite(r,"<HTML><BODY>",12);
+    
+    HTTPWrite(r,buffer,strlen(buffer));
+
+    HTTPWrite(r,"</BODY></HTML>",14);
+
+    HTTPWriteEnd(r);
+}
+
+abyss_bool HandleTime(TSession *r)
+{
+    char z[50];
+    time_t ltime;
+    TDate date;
+
+    if (strcmp(r->uri,"/time")!=0)
+        return FALSE;
+
+    if (!RequestAuth(r,"Mot de passe","moez","hello"))
+        return TRUE;
+
+    time( &ltime );
+    DateFromGMT(&date,ltime);
+    
+
+    strcpy(z,"The time is ");
+    DateToString(&date,z+strlen(z));
+
+    Answer(r,200,z);
+
+    return TRUE;
+}
+
+abyss_bool HandleDump(TSession *r)
+{
+    char z[50];
+
+    if (strcmp(r->uri,"/name")!=0)
+        return FALSE;
+
+    sprintf(z,"Server name is %s", (r->server)->name );
+    Answer(r,200,z);
+
+    return TRUE;
+}
+
+abyss_bool HandleStatus(TSession *r)
+{
+    uint32_t status;
+
+    if (sscanf(r->uri,"/status/%d",&status)<=0)
+        return FALSE;
+
+    ResponseStatus(r,(uint16_t)status);
+
+    return TRUE;
+}
+
+abyss_bool HandleMIMEType(TSession *r)
+{
+    char *m;
+
+    if (strncmp(r->uri,"/mime/",6)!=0)
+        return FALSE;
+
+    m=MIMETypeFromExt(r->uri+6);
+    if (!m)
+        m="(none)";
+
+    Answer(r,200,m);
+
+    return TRUE;
+}
+
+#ifdef _UNIX
+static void sigterm(int sig)
+{
+    TraceExit("Signal %d received. Exiting...\n",sig);
+}
+
+
+
+static void
+sigchld(int const signalClass) {
+
+    abyss_bool childrenLeft;
+    abyss_bool error;
+
+    childrenLeft = true;
+    error = false;
+
+    /* Reap defunct children until there aren't any more. */
+    while (childrenLeft && !error) {
+        int status;
+        pid_t rc;
+        rc = waitpid((pid_t) -1, &status, WNOHANG);
+
+        if (rc == 0)
+            childrenLeft = false;
+        else if (rc < 0) {
+            /* because of ptrace */
+            if (errno == EINTR) {
+                /* ptrace causes this */
+            } else
+                error = true;
+        } else {
+            /* We reaped a child. */
+            pid_t const pid = rc;
+            ThreadHandleSigchld(pid);
+        }
+    }
+}
+#endif _UNIX
+
+
+
+int main(int argc,char **argv)
+{
+    TServer srv;
+    char *p,*conffile=DEFAULT_CONF_FILE;
+    abyss_bool err=FALSE;
+    char *name=argv[0];
+
+    while (p=*(++argv))
+    {
+        if ((*p=='-') && (*(p+1)))
+            if (*(p+2)=='\0')
+                switch (*(p+1))
+                {
+                case 'c':
+                    argv++;
+                    if (*argv)
+                        conffile=*argv;
+                    else
+                        err=TRUE;
+                    break;
+                default:
+                    err=TRUE;
+                }
+            else
+                err=TRUE;
+        else
+            err=TRUE;
+    };
+
+    if (err)
+    {
+        help(name);
+        exit(1);
+    };
+
+    DateInit();
+
+    MIMETypeInit();
+
+    ServerCreate(&srv,"HTTPServer",80,DEFAULT_DOCS,NULL);
+
+    ConfReadServerFile(conffile,&srv);
+
+    ServerAddHandler(&srv,HandleTime);
+    ServerAddHandler(&srv,HandleDump);
+    ServerAddHandler(&srv,HandleStatus);
+    ServerAddHandler(&srv,HandleMIMEType);
+
+    ServerInit(&srv);
+
+#ifdef _UNIX
+    /* Catch various termination signals. */
+    signal(SIGTERM,sigterm);
+    signal(SIGINT,sigterm);
+    signal(SIGHUP,sigterm);
+    signal(SIGUSR1,sigterm);
+
+    /* Catch defunct children. */
+    signal(SIGCHLD,sigchld);
+#endif
+
+    ServerDaemonize(srv);
+
+    ServerRun(&srv);
+
+    return 0;
+}
diff --git a/lib/abyss/src/response.c b/lib/abyss/src/response.c
new file mode 100644 (file)
index 0000000..89fb69c
--- /dev/null
@@ -0,0 +1,657 @@
+/*=============================================================================
+                             response
+===============================================================================
+  This module contains callbacks from and services for a request handler.
+
+  Copyright information is at the end of the file
+=============================================================================*/
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include "xmlrpc_config.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "server.h"
+#include "session.h"
+#include "conn.h"
+#include "token.h"
+#include "date.h"
+#include "data.h"
+#include "abyss_info.h"
+#include "http.h"
+
+
+
+void
+ResponseError(TSession * const sessionP) {
+
+    const char * const reason = HTTPReasonByStatus(sessionP->status);
+    const char * errorDocument;
+
+    ResponseAddField(sessionP, "Content-type", "text/html");
+
+    ResponseWriteStart(sessionP);
+    
+    xmlrpc_asprintf(&errorDocument,
+                    "<HTML><HEAD><TITLE>Error %d</TITLE></HEAD>"
+                    "<BODY><H1>Error %d</H1><P>%s</P>" SERVER_HTML_INFO 
+                    "</BODY></HTML>",
+                    sessionP->status, sessionP->status, reason);
+    
+    ConnWrite(sessionP->conn, errorDocument, strlen(errorDocument)); 
+
+    xmlrpc_strfree(errorDocument);
+}
+
+
+
+abyss_bool
+ResponseChunked(TSession * const sessionP) {
+    /* This is only a hope, things will be real only after a call of
+       ResponseWriteStart()
+    */
+    assert(!sessionP->responseStarted);
+
+    sessionP->chunkedwrite =
+        (sessionP->version.major > 1) ||
+        (sessionP->version.major == 1 && (sessionP->version.minor >= 1));
+
+    sessionP->chunkedwritemode = TRUE;
+
+    return TRUE;
+}
+
+
+
+void
+ResponseStatus(TSession * const sessionP,
+               uint16_t   const code) {
+
+    sessionP->status = code;
+}
+
+
+
+uint16_t
+ResponseStatusFromErrno(int const errnoArg) {
+
+    uint16_t code;
+
+    switch (errnoArg) {
+    case EACCES:
+        code=403;
+        break;
+    case ENOENT:
+        code=404;
+        break;
+    default:
+        code=500;
+    }
+    return code;
+}
+
+
+
+void
+ResponseStatusErrno(TSession * const sessionP) {
+
+    ResponseStatus(sessionP, ResponseStatusFromErrno(errno));
+}
+
+
+
+abyss_bool
+ResponseAddField(TSession *   const sessionP,
+                 const char * const name,
+                 const char * const value) {
+
+    return TableAdd(&sessionP->response_headers, name, value);
+}
+
+
+
+static void
+addDateHeader(TSession * const sessionP) {
+
+    char dateValue[64];
+    abyss_bool validDate;
+
+    validDate = DateToString(&sessionP->date, dateValue);
+
+    if (sessionP->status >= 200 && validDate)
+        ResponseAddField(sessionP, "Date", dateValue);
+}
+
+
+
+void
+ResponseWriteStart(TSession * const sessionP) {
+
+    struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP;
+
+    unsigned int i;
+
+    assert(!sessionP->responseStarted);
+
+    if (sessionP->status == 0) {
+        // Handler hasn't set status.  That's an error
+        sessionP->status = 500;
+    }
+
+    sessionP->responseStarted = TRUE;
+
+    {
+        const char * const reason = HTTPReasonByStatus(sessionP->status);
+        const char * line;
+        xmlrpc_asprintf(&line,"HTTP/1.1 %u %s\r\n", sessionP->status, reason);
+        ConnWrite(sessionP->conn, line, strlen(line));
+        xmlrpc_strfree(line);
+    }
+
+    if (HTTPKeepalive(sessionP)) {
+        const char * keepaliveValue;
+        
+        ResponseAddField(sessionP, "Connection", "Keep-Alive");
+
+        xmlrpc_asprintf(&keepaliveValue, "timeout=%u, max=%u",
+                        srvP->keepalivetimeout, srvP->keepalivemaxconn);
+
+        ResponseAddField(sessionP, "Keep-Alive", keepaliveValue);
+
+        xmlrpc_strfree(keepaliveValue);
+    } else
+        ResponseAddField(sessionP, "Connection", "close");
+    
+    if (sessionP->chunkedwrite && sessionP->chunkedwritemode)
+        ResponseAddField(sessionP, "Transfer-Encoding", "chunked");
+
+    addDateHeader(sessionP);
+
+    /* Generation of the server field */
+    if (srvP->advertise)
+        ResponseAddField(sessionP, "Server", SERVER_HVERSION);
+
+    /* send all the fields */
+    for (i = 0; i < sessionP->response_headers.size; ++i) {
+        TTableItem * const ti = &sessionP->response_headers.item[i];
+        const char * line;
+        xmlrpc_asprintf(&line, "%s: %s\r\n", ti->name, ti->value);
+        ConnWrite(sessionP->conn, line, strlen(line));
+        xmlrpc_strfree(line);
+    }
+
+    ConnWrite(sessionP->conn, "\r\n", 2);  
+}
+
+
+
+abyss_bool
+ResponseWriteBody(TSession *   const sessionP,
+                  const char * const data,
+                  uint32_t     const len) {
+
+    return HTTPWriteBodyChunk(sessionP, data, len);
+}
+
+
+
+abyss_bool
+ResponseWriteEnd(TSession * const sessionP) {
+
+    return HTTPWriteEndChunk(sessionP);
+}
+
+
+
+abyss_bool
+ResponseContentType(TSession *   const serverP,
+                    const char * const type) {
+
+    return ResponseAddField(serverP, "Content-type", type);
+}
+
+
+
+abyss_bool
+ResponseContentLength(TSession * const sessionP,
+                      uint64_t   const len) {
+    char contentLengthValue[32];
+    
+    sprintf(contentLengthValue, "%llu", len);
+
+    return ResponseAddField(sessionP, "Content-length", contentLengthValue);
+}
+
+
+/*********************************************************************
+** MIMEType
+*********************************************************************/
+
+struct MIMEType {
+    TList typeList;
+    TList extList;
+    TPool pool;
+};
+
+
+static MIMEType * globalMimeTypeP = NULL;
+
+
+
+MIMEType *
+MIMETypeCreate(void) {
+    MIMEType * MIMETypeP;
+
+    MALLOCVAR(MIMETypeP);
+
+    if (MIMETypeP) {
+        ListInit(&MIMETypeP->typeList);
+        ListInit(&MIMETypeP->extList);
+        PoolCreate(&MIMETypeP->pool, 1024);
+    }
+    return MIMETypeP;
+}
+
+
+
+void
+MIMETypeDestroy(MIMEType * const MIMETypeP) {
+
+    PoolFree(&MIMETypeP->pool);
+}
+
+
+
+void
+MIMETypeInit(void) {
+
+    if (globalMimeTypeP != NULL)
+        abort();
+
+    globalMimeTypeP = MIMETypeCreate();
+}
+
+
+
+void
+MIMETypeTerm(void) {
+
+    if (globalMimeTypeP == NULL)
+        abort();
+
+    MIMETypeDestroy(globalMimeTypeP);
+
+    globalMimeTypeP = NULL;
+}
+
+
+
+static void
+mimeTypeAdd(MIMEType *   const MIMETypeP,
+            const char * const type,
+            const char * const ext,
+            abyss_bool * const successP) {
+    
+    uint16_t index;
+    void * mimeTypesItem;
+    abyss_bool typeIsInList;
+
+    assert(MIMETypeP != NULL);
+
+    typeIsInList = ListFindString(&MIMETypeP->typeList, type, &index);
+    if (typeIsInList)
+        mimeTypesItem = MIMETypeP->typeList.item[index];
+    else
+        mimeTypesItem = (void*)PoolStrdup(&MIMETypeP->pool, type);
+
+    if (mimeTypesItem) {
+        abyss_bool extIsInList;
+        extIsInList = ListFindString(&MIMETypeP->extList, ext, &index);
+        if (extIsInList) {
+            MIMETypeP->typeList.item[index] = mimeTypesItem;
+            *successP = TRUE;
+        } else {
+            void * extItem = (void*)PoolStrdup(&MIMETypeP->pool, ext);
+            if (extItem) {
+                abyss_bool addedToMimeTypes;
+
+                addedToMimeTypes =
+                    ListAdd(&MIMETypeP->typeList, mimeTypesItem);
+                if (addedToMimeTypes) {
+                    abyss_bool addedToExt;
+                    
+                    addedToExt = ListAdd(&MIMETypeP->extList, extItem);
+                    *successP = addedToExt;
+                    if (!*successP)
+                        ListRemove(&MIMETypeP->typeList);
+                } else
+                    *successP = FALSE;
+                if (!*successP)
+                    PoolReturn(&MIMETypeP->pool, extItem);
+            } else
+                *successP = FALSE;
+        }
+    } else
+        *successP = FALSE;
+}
+
+
+
+
+abyss_bool
+MIMETypeAdd2(MIMEType *   const MIMETypeArg,
+             const char * const type,
+             const char * const ext) {
+
+    MIMEType * MIMETypeP = MIMETypeArg ? MIMETypeArg : globalMimeTypeP;
+
+    abyss_bool success;
+
+    if (MIMETypeP == NULL)
+        success = FALSE;
+    else 
+        mimeTypeAdd(MIMETypeP, type, ext, &success);
+
+    return success;
+}
+
+
+
+abyss_bool
+MIMETypeAdd(const char * const type,
+            const char * const ext) {
+
+    return MIMETypeAdd2(globalMimeTypeP, type, ext);
+}
+
+
+
+static const char *
+mimeTypeFromExt(MIMEType *   const MIMETypeP,
+                const char * const ext) {
+
+    const char * retval;
+    uint16_t extindex;
+    abyss_bool extIsInList;
+
+    assert(MIMETypeP != NULL);
+
+    extIsInList = ListFindString(&MIMETypeP->extList, ext, &extindex);
+    if (!extIsInList)
+        retval = NULL;
+    else
+        retval = MIMETypeP->typeList.item[extindex];
+    
+    return retval;
+}
+
+
+
+const char *
+MIMETypeFromExt2(MIMEType *   const MIMETypeArg,
+                 const char * const ext) {
+
+    const char * retval;
+
+    MIMEType * MIMETypeP = MIMETypeArg ? MIMETypeArg : globalMimeTypeP;
+
+    if (MIMETypeP == NULL)
+        retval = NULL;
+    else
+        retval = mimeTypeFromExt(MIMETypeP, ext);
+
+    return retval;
+}
+
+
+
+const char *
+MIMETypeFromExt(const char * const ext) {
+
+    return MIMETypeFromExt2(globalMimeTypeP, ext);
+}
+
+
+
+static void
+findExtension(const char *  const fileName,
+              const char ** const extP) {
+
+    unsigned int extPos = 0;  /* stifle unset variable warning */
+        /* Running estimation of where in fileName[] the extension starts */
+    abyss_bool extFound;
+    unsigned int i;
+
+    /* We're looking for the last dot after the last slash */
+    for (i = 0, extFound = FALSE; fileName[i]; ++i) {
+        char const c = fileName[i];
+        
+        if (c == '.') {
+            extFound = TRUE;
+            extPos = i + 1;
+        }
+        if (c == '/')
+            extFound = FALSE;
+    }
+
+    if (extFound)
+        *extP = &fileName[extPos];
+    else
+        *extP = NULL;
+}
+
+
+
+static const char *
+mimeTypeFromFileName(MIMEType *   const MIMETypeP,
+                     const char * const fileName) {
+
+    const char * retval;
+    const char * ext;
+
+    assert(MIMETypeP != NULL);
+    
+    findExtension(fileName, &ext);
+
+    if (ext)
+        retval = MIMETypeFromExt2(MIMETypeP, ext);
+    else
+        retval = "application/octet-stream";
+
+    return retval;
+}
+
+
+
+const char *
+MIMETypeFromFileName2(MIMEType *   const MIMETypeArg,
+                      const char * const fileName) {
+
+    const char * retval;
+    
+    MIMEType * MIMETypeP = MIMETypeArg ? MIMETypeArg : globalMimeTypeP;
+
+    if (MIMETypeP == NULL)
+        retval = NULL;
+    else
+        retval = mimeTypeFromFileName(MIMETypeP, fileName);
+
+    return retval;
+}
+
+
+
+const char *
+MIMETypeFromFileName(const char * const fileName) {
+
+    return MIMETypeFromFileName2(globalMimeTypeP, fileName);
+}
+
+
+
+static abyss_bool
+fileContainsText(const char * const fileName) {
+/*----------------------------------------------------------------------------
+   Return true iff we can read the contents of the file named 'fileName'
+   and see that it appears to be composed of plain text characters.
+-----------------------------------------------------------------------------*/
+    abyss_bool retval;
+    abyss_bool fileOpened;
+    TFile file;
+
+    fileOpened = FileOpen(&file, fileName, O_BINARY | O_RDONLY);
+    if (fileOpened) {
+        char const ctlZ = 26;
+        unsigned char buffer[80];
+        int32_t readRc;
+        unsigned int i;
+
+        readRc = FileRead(&file, buffer, sizeof(buffer));
+       
+        if (readRc >= 0) {
+            unsigned int bytesRead = readRc;
+            abyss_bool nonTextFound;
+
+            nonTextFound = FALSE;  /* initial value */
+    
+            for (i = 0; i < bytesRead; ++i) {
+                char const c = buffer[i];
+                if (c < ' ' && !isspace(c) && c != ctlZ)
+                    nonTextFound = TRUE;
+            }
+            retval = !nonTextFound;
+        } else
+            retval = FALSE;
+        FileClose(&file);
+    } else
+        retval = FALSE;
+
+    return retval;
+}
+
+
+static const char *
+mimeTypeGuessFromFile(MIMEType *   const MIMETypeP,
+                      const char * const fileName) {
+
+    const char * retval;
+    const char * ext;
+
+    findExtension(fileName, &ext);
+
+    retval = NULL;
+
+    if (ext && MIMETypeP)
+        retval = MIMETypeFromExt2(MIMETypeP, ext);
+    
+    if (!retval) {
+        if (fileContainsText(fileName))
+            retval = "text/plain";
+        else
+            retval = "application/octet-stream";  
+    }
+    return retval;
+}
+
+
+
+const char *
+MIMETypeGuessFromFile2(MIMEType *   const MIMETypeArg,
+                       const char * const fileName) {
+
+    return mimeTypeGuessFromFile(MIMETypeArg ? MIMETypeArg : globalMimeTypeP,
+                                 fileName);
+}
+
+
+
+const char *
+MIMETypeGuessFromFile(const char * const fileName) {
+
+    return mimeTypeGuessFromFile(globalMimeTypeP, fileName);
+}
+
+                                  
+
+/*********************************************************************
+** Base64
+*********************************************************************/
+
+void Base64Encode(char *s,char *d)
+{
+    /* Conversion table. */
+    static char tbl[64] = {
+        'A','B','C','D','E','F','G','H',
+        'I','J','K','L','M','N','O','P',
+        'Q','R','S','T','U','V','W','X',
+        'Y','Z','a','b','c','d','e','f',
+        'g','h','i','j','k','l','m','n',
+        'o','p','q','r','s','t','u','v',
+        'w','x','y','z','0','1','2','3',
+        '4','5','6','7','8','9','+','/'
+    };
+
+    uint32_t i,length=strlen(s);
+    char *p=d;
+    
+    /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
+    for (i = 0; i < length; i += 3)
+    {
+        *p++ = tbl[s[0] >> 2];
+        *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
+        *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
+        *p++ = tbl[s[2] & 0x3f];
+        s += 3;
+    }
+    
+    /* Pad the result if necessary... */
+    if (i == length + 1)
+        *(p - 1) = '=';
+    else if (i == length + 2)
+        *(p - 1) = *(p - 2) = '=';
+    
+    /* ...and zero-terminate it. */
+    *p = '\0';
+}
+
+/******************************************************************************
+**
+** http.c
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
diff --git a/lib/abyss/src/server.c b/lib/abyss/src/server.c
new file mode 100644 (file)
index 0000000..8e5af56
--- /dev/null
@@ -0,0 +1,1794 @@
+/* Copyright information is at end of file */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#ifdef WIN32
+  #include <io.h>
+#else
+  #include <unistd.h>
+  #include <grp.h>
+#endif
+#include <fcntl.h>
+
+#include "xmlrpc_config.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/sleep_int.h"
+
+#include "xmlrpc-c/abyss.h"
+#include "trace.h"
+#include "session.h"
+#include "conn.h"
+#include "socket.h"
+#ifdef WIN32
+  #include "socket_win.h"
+#else
+  #include "socket_unix.h"
+#endif
+#include "http.h"
+#include "date.h"
+#include "abyss_info.h"
+
+#include "server.h"
+
+
+void
+ServerTerminate(TServer * const serverP) {
+
+    struct _TServer * const srvP = serverP->srvP;
+
+    srvP->terminationRequested = true;
+}
+
+
+
+void
+ServerResetTerminate(TServer * const serverP) {
+
+    struct _TServer * const srvP = serverP->srvP;
+
+    srvP->terminationRequested = false;
+}
+
+
+
+typedef int (*TQSortProc)(const void *, const void *);
+
+static int
+cmpfilenames(const TFileInfo **f1,const TFileInfo **f2) {
+    if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))
+        return (-1);
+    if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))
+        return 1;
+
+    return strcmp((*f1)->name,(*f2)->name);
+}
+
+static int
+cmpfiledates(const TFileInfo **f1,const TFileInfo **f2) {
+    if (((*f1)->attrib & A_SUBDIR) && !((*f2)->attrib & A_SUBDIR))
+        return (-1);
+    if (!((*f1)->attrib & A_SUBDIR) && ((*f2)->attrib & A_SUBDIR))
+        return 1;
+
+    return ((*f1)->time_write-(*f2)->time_write);
+}
+
+
+
+static void
+determineSortType(const char *  const query,
+                  abyss_bool *  const ascendingP,
+                  uint16_t *    const sortP,
+                  abyss_bool *  const textP,
+                  const char ** const errorP) {
+
+    *ascendingP = TRUE;
+    *sortP = 1;
+    *textP = FALSE;
+    *errorP = NULL;
+    
+    if (query) {
+        if (xmlrpc_streq(query, "plain"))
+            *textP = TRUE;
+        else if (xmlrpc_streq(query, "name-up")) {
+            *sortP = 1;
+            *ascendingP = TRUE;
+        } else if (xmlrpc_streq(query, "name-down")) {
+            *sortP = 1;
+            *ascendingP = FALSE;
+        } else if (xmlrpc_streq(query, "date-up")) {
+            *sortP = 2;
+            *ascendingP = TRUE;
+        } else if (xmlrpc_streq(query, "date-down")) {
+            *sortP = 2;
+            *ascendingP = FALSE;
+        } else  {
+            xmlrpc_asprintf(errorP, "invalid query value '%s'", query);
+        }
+    }
+}
+
+
+
+static void
+generateListing(TList *       const listP,
+                char *        const z,
+                const char *  const uri,
+                TPool *       const poolP,
+                const char ** const errorP,
+                uint16_t *    const responseStatusP) {
+    
+    TFileInfo fileinfo;
+    TFileFind findhandle;
+
+    *errorP = NULL;
+
+    if (!FileFindFirst(&findhandle, z, &fileinfo)) {
+        *responseStatusP = ResponseStatusFromErrno(errno);
+        xmlrpc_asprintf(errorP, "Can't read first entry in directory");
+    } else {
+        ListInit(listP);
+
+        do {
+            TFileInfo * fi;
+            /* Files whose names start with a dot are ignored */
+            /* This includes implicitly the ./ and ../ */
+            if (*fileinfo.name == '.') {
+                if (xmlrpc_streq(fileinfo.name, "..")) {
+                    if (xmlrpc_streq(uri, "/"))
+                        continue;
+                } else
+                    continue;
+            }
+            fi = (TFileInfo *)PoolAlloc(poolP, sizeof(fileinfo));
+            if (fi) {
+                abyss_bool success;
+                memcpy(fi, &fileinfo, sizeof(fileinfo));
+                success =  ListAdd(listP, fi);
+                if (!success)
+                    xmlrpc_asprintf(errorP, "ListAdd() failed");
+            } else
+                xmlrpc_asprintf(errorP, "PoolAlloc() failed.");
+        } while (!*errorP && FileFindNext(&findhandle, &fileinfo));
+
+        if (*errorP) {
+            *responseStatusP = 500;
+            ListFree(listP);
+        }            
+        FileFindClose(&findhandle);
+    }
+}
+
+
+
+static void
+sendDirectoryDocument(TList *      const listP,
+                      abyss_bool   const ascending,
+                      uint16_t     const sort,
+                      abyss_bool   const text,
+                      const char * const uri,
+                      MIMEType *   const mimeTypeP,
+                      TSession *   const sessionP,
+                      char *       const z) {
+
+    char *p,z1[26],z2[20],z3[9],u;
+    const char * z4;
+    int16_t i;
+    uint32_t k;
+
+    if (text) {
+        sprintf(z, "Index of %s" CRLF, uri);
+        i = strlen(z)-2;
+        p = z + i + 2;
+
+        while (i > 0) {
+            *(p++) = '-';
+            --i;
+        }
+
+        *p = '\0';
+        strcat(z, CRLF CRLF
+               "Name                      Size      "
+               "Date-Time             Type" CRLF
+               "------------------------------------"
+               "--------------------------------------------"CRLF);
+    } else {
+        sprintf(z, "<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>"
+                "<H1>Index of %s</H1><PRE>",
+                uri, uri);
+        strcat(z, "Name                      Size      "
+               "Date-Time             Type<HR WIDTH=100%>"CRLF);
+    }
+
+    HTTPWriteBodyChunk(sessionP, z, strlen(z));
+
+    /* Sort the files */
+    qsort(listP->item, listP->size, sizeof(void *),
+          (TQSortProc)(sort == 1 ? cmpfilenames : cmpfiledates));
+    
+    /* Write the listing */
+    if (ascending)
+        i = 0;
+    else
+        i = listP->size - 1;
+
+    while ((i < listP->size) && (i >= 0)) {
+        TFileInfo * fi;
+        struct tm ftm;
+
+        fi = listP->item[i];
+
+        if (ascending)
+            ++i;
+        else
+            --i;
+            
+        strcpy(z, fi->name);
+
+        k = strlen(z);
+
+        if (fi->attrib & A_SUBDIR) {
+            z[k++] = '/';
+            z[k] = '\0';
+        }
+
+        if (k > 24) {
+            z[10] = '\0';
+            strcpy(z1, z);
+            strcat(z1, "...");
+            strcat(z1, z + k - 11);
+            k = 24;
+            p = z1 + 24;
+        } else {
+            strcpy(z1, z);
+            
+            ++k;
+            p = z1 + k;
+            while (k < 25)
+                z1[k++] = ' ';
+            
+            z1[25] = '\0';
+        }
+
+        ftm = *gmtime(&fi->time_write);
+        sprintf(z2, "%02u/%02u/%04u %02u:%02u:%02u",ftm.tm_mday,ftm.tm_mon+1,
+                ftm.tm_year+1900,ftm.tm_hour,ftm.tm_min,ftm.tm_sec);
+
+        if (fi->attrib & A_SUBDIR) {
+            strcpy(z3, "   --  ");
+            z4 = "Directory";
+        } else {
+            if (fi->size < 9999)
+                u = 'b';
+            else {
+                fi->size /= 1024;
+                if (fi->size < 9999)
+                    u = 'K';
+                else {
+                    fi->size /= 1024;
+                    if (fi->size < 9999)
+                        u = 'M';
+                    else
+                        u = 'G';
+                }
+            }
+                
+            sprintf(z3, "%5llu %c", fi->size, u);
+            
+            if (xmlrpc_streq(fi->name, ".."))
+                z4 = "";
+            else
+                z4 = MIMETypeFromFileName2(mimeTypeP, fi->name);
+
+            if (!z4)
+                z4 = "Unknown";
+        }
+
+        if (text)
+            sprintf(z, "%s%s %s    %s   %s"CRLF, z1, p, z3, z2, z4);
+        else
+            sprintf(z, "<A HREF=\"%s%s\">%s</A>%s %s    %s   %s"CRLF,
+                    fi->name, fi->attrib & A_SUBDIR ? "/" : "",
+                    z1, p, z3, z2, z4);
+
+        HTTPWriteBodyChunk(sessionP, z, strlen(z));
+    }
+        
+    /* Write the tail of the file */
+    if (text)
+        strcpy(z, SERVER_PLAIN_INFO);
+    else
+        strcpy(z, "</PRE>" SERVER_HTML_INFO "</BODY></HTML>" CRLF CRLF);
+    
+    HTTPWriteBodyChunk(sessionP, z, strlen(z));
+}
+
+
+
+static void
+fileDate(TSession * const sessionP,
+         time_t     const statFilemodTime,
+         TDate *    const fileDateP) {
+
+    abyss_bool haveDate;
+    TDate filemodDate;
+
+    haveDate = DateFromLocal(&filemodDate, statFilemodTime);
+
+    if (haveDate) {
+        if (DateCompare(&sessionP->date, &filemodDate) < 0)
+            *fileDateP = sessionP->date;
+        else
+            *fileDateP = filemodDate;
+    } else
+        *fileDateP = sessionP->date;
+}
+
+
+
+static abyss_bool
+ServerDirectoryHandler(TSession * const r,
+                       char *     const z,
+                       time_t     const fileModTime,
+                       MIMEType * const mimeTypeP) {
+
+    TList list;
+    abyss_bool text;
+    abyss_bool ascending;
+    uint16_t sort;    /* 1=by name, 2=by date */
+    TPool pool;
+    TDate date;
+    const char * error;
+    uint16_t responseStatus;
+    TDate dirdate;
+    const char * imsHdr;
+    
+    determineSortType(r->request_info.query, &ascending, &sort, &text, &error);
+
+    if (error) {
+        ResponseStatus(r,400);
+        xmlrpc_strfree(error);
+        return TRUE;
+    }
+
+    fileDate(r, fileModTime, &dirdate);
+
+    imsHdr = RequestHeaderValue(r, "If-Modified-Since");
+    if (imsHdr) {
+        if (DateDecode(imsHdr, &date)) {
+            if (DateCompare(&dirdate, &date) <= 0) {
+                ResponseStatus(r, 304);
+                ResponseWrite(r);
+                return TRUE;
+            }
+        }
+    }
+
+    if (!PoolCreate(&pool, 1024)) {
+        ResponseStatus(r, 500);
+        return TRUE;
+    }
+
+    generateListing(&list, z, r->request_info.uri,
+                    &pool, &error, &responseStatus);
+    if (error) {
+        ResponseStatus(r, responseStatus);
+        xmlrpc_strfree(error);
+        PoolFree(&pool);
+        return TRUE;
+    }
+
+    /* Send something to the user to show that we are still alive */
+    ResponseStatus(r, 200);
+    ResponseContentType(r, (text ? "text/plain" : "text/html"));
+
+    if (DateToString(&dirdate, z))
+        ResponseAddField(r, "Last-Modified", z);
+    
+    ResponseChunked(r);
+    ResponseWrite(r);
+
+    if (r->request_info.method!=m_head)
+        sendDirectoryDocument(&list, ascending, sort, text,
+                              r->request_info.uri, mimeTypeP, r, z);
+
+    HTTPWriteEndChunk(r);
+
+    /* Free memory and exit */
+    ListFree(&list);
+    PoolFree(&pool);
+
+    return TRUE;
+}
+
+
+
+#define BOUNDARY    "##123456789###BOUNDARY"
+
+static void
+sendBody(TSession *   const sessionP,
+         TFile *      const fileP,
+         uint64_t     const filesize,
+         const char * const mediatype,
+         uint64_t     const start0,
+         uint64_t     const end0,
+         char *       const z) {
+
+    if (sessionP->ranges.size == 0)
+        ConnWriteFromFile(sessionP->conn, fileP, 0, filesize - 1, z, 4096, 0);
+    else if (sessionP->ranges.size == 1)
+        ConnWriteFromFile(sessionP->conn, fileP, start0, end0, z, 4096, 0);
+    else {
+        uint64_t i;
+        for (i = 0; i <= sessionP->ranges.size; ++i) {
+            ConnWrite(sessionP->conn,"--", 2);
+            ConnWrite(sessionP->conn, BOUNDARY, strlen(BOUNDARY));
+            ConnWrite(sessionP->conn, CRLF, 2);
+
+            if (i < sessionP->ranges.size) {
+                uint64_t start;
+                uint64_t end;
+                abyss_bool decoded;
+                    
+                decoded = RangeDecode((char *)(sessionP->ranges.item[i]),
+                                      filesize,
+                                      &start, &end);
+                if (decoded) {
+                    /* Entity header, not response header */
+                    sprintf(z, "Content-type: %s" CRLF
+                            "Content-range: bytes %llu-%llu/%llu" CRLF
+                            "Content-length: %llu" CRLF
+                            CRLF, mediatype, start, end,
+                            filesize, end-start+1);
+
+                    ConnWrite(sessionP->conn, z, strlen(z));
+
+                    ConnWriteFromFile(sessionP->conn, fileP, start, end, z,
+                                      4096, 0);
+                }
+            }
+        }
+    }
+}
+
+
+
+static abyss_bool
+ServerFileHandler(TSession * const r,
+                  char *     const z,
+                  time_t     const fileModTime,
+                  MIMEType * const mimeTypeP) {
+
+    const char * mediatype;
+    TFile file;
+    uint64_t filesize;
+    uint64_t start;
+    uint64_t end;
+    TDate date;
+    char * p;
+    TDate filedate;
+    
+    mediatype = MIMETypeGuessFromFile2(mimeTypeP, z);
+
+    if (!FileOpen(&file,z,O_BINARY | O_RDONLY)) {
+        ResponseStatusErrno(r);
+        return TRUE;
+    }
+
+    fileDate(r, fileModTime, &filedate);
+
+    p = RequestHeaderValue(r, "if-modified-since");
+    if (p) {
+        if (DateDecode(p,&date)) {
+            if (DateCompare(&filedate, &date) <= 0) {
+                ResponseStatus(r, 304);
+                ResponseWrite(r);
+                return TRUE;
+            } else
+                r->ranges.size = 0;
+        }
+    }
+    filesize = FileSize(&file);
+
+    switch (r->ranges.size) {
+    case 0:
+        ResponseStatus(r, 200);
+        break;
+
+    case 1: {
+        abyss_bool decoded;
+        decoded = RangeDecode((char *)(r->ranges.item[0]), filesize,
+                              &start, &end);
+        if (!decoded) {
+            ListFree(&(r->ranges));
+            ResponseStatus(r, 200);
+            break;
+        }
+        
+        sprintf(z, "bytes %llu-%llu/%llu", start, end, filesize);
+
+        ResponseAddField(r, "Content-range", z);
+        ResponseContentLength(r, end - start + 1);
+        ResponseStatus(r, 206);
+    } break;
+
+    default:
+        ResponseContentType(r, "multipart/ranges; boundary=" BOUNDARY);
+        ResponseStatus(r, 206);
+        break;
+    }
+    
+    if (r->ranges.size == 0) {
+        ResponseContentLength(r, filesize);
+        ResponseContentType(r, mediatype);
+    }
+    
+    if (DateToString(&filedate, z))
+        ResponseAddField(r, "Last-Modified", z);
+
+    ResponseWrite(r);
+
+    if (r->request_info.method != m_head)
+        sendBody(r, &file, filesize, mediatype, start, end, z);
+
+    FileClose(&file);
+
+    return TRUE;
+}
+
+
+
+static abyss_bool
+ServerDefaultHandlerFunc(TSession * const sessionP) {
+
+    struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP;
+
+    char *p;
+    char z[4096];
+    TFileStat fs;
+    unsigned int i;
+    abyss_bool endingslash=FALSE;
+
+    if (!RequestValidURIPath(sessionP)) {
+        ResponseStatus(sessionP, 400);
+        return TRUE;
+    }
+
+    /* Must check for * (asterisk uri) in the future */
+    if (sessionP->request_info.method == m_options) {
+        ResponseAddField(sessionP, "Allow", "GET, HEAD");
+        ResponseContentLength(sessionP, 0);
+        ResponseStatus(sessionP, 200);
+        return TRUE;
+    }
+
+    if ((sessionP->request_info.method != m_get) &&
+        (sessionP->request_info.method != m_head)) {
+        ResponseAddField(sessionP, "Allow", "GET, HEAD");
+        ResponseStatus(sessionP, 405);
+        return TRUE;
+    }
+
+    strcpy(z, srvP->filespath);
+    strcat(z, sessionP->request_info.uri);
+
+    p = z + strlen(z) - 1;
+    if (*p == '/') {
+        endingslash = TRUE;
+        *p = '\0';
+    }
+
+#ifdef WIN32
+    p = z;
+    while (*p) {
+        if ((*p) == '/')
+            *p= '\\';
+
+        ++p;
+    }
+#endif  /* WIN32 */
+
+    if (!FileStat(z, &fs)) {
+        ResponseStatusErrno(sessionP);
+        return TRUE;
+    }
+
+    if (fs.st_mode & S_IFDIR) {
+        /* Redirect to the same directory but with the ending slash
+        ** to avoid problems with some browsers (IE for examples) when
+        ** they generate relative urls */
+        if (!endingslash) {
+            strcpy(z, sessionP->request_info.uri);
+            p = z+strlen(z);
+            *p = '/';
+            *(p+1) = '\0';
+            ResponseAddField(sessionP, "Location", z);
+            ResponseStatus(sessionP, 302);
+            ResponseWrite(sessionP);
+            return TRUE;
+        }
+
+        *p = DIRECTORY_SEPARATOR[0];
+        ++p;
+
+        i = srvP->defaultfilenames.size;
+        while (i-- > 0) {
+            *p = '\0';        
+            strcat(z, (srvP->defaultfilenames.item[i]));
+            if (FileStat(z, &fs)) {
+                if (!(fs.st_mode & S_IFDIR))
+                    return ServerFileHandler(sessionP, z, fs.st_mtime,
+                                             srvP->mimeTypeP);
+            }
+        }
+
+        *(p-1) = '\0';
+        
+        if (!FileStat(z, &fs)) {
+            ResponseStatusErrno(sessionP);
+            return TRUE;
+        }
+        return ServerDirectoryHandler(sessionP, z, fs.st_mtime,
+                                      srvP->mimeTypeP);
+    } else
+        return ServerFileHandler(sessionP, z, fs.st_mtime,
+                                 srvP->mimeTypeP);
+}
+
+
+
+static void
+initUnixStuff(struct _TServer * const srvP) {
+#ifndef WIN32
+    srvP->pidfile = srvP->uid = srvP->gid = -1;
+#endif
+}
+
+
+
+static abyss_bool
+logOpen(struct _TServer * const srvP) {
+
+    abyss_bool success;
+
+    success = FileOpenCreate(&srvP->logfile, srvP->logfilename,
+                             O_WRONLY | O_APPEND);
+    if (success) {
+        abyss_bool success;
+        success = MutexCreate(&srvP->logmutex);
+        if (success)
+            srvP->logfileisopen = TRUE;
+        else
+            TraceMsg("Can't create mutex for log file");
+
+        if (!success)
+            FileClose(&srvP->logfile);
+    } else
+        TraceMsg("Can't open log file '%s'", srvP->logfilename);
+
+    return success;
+}
+
+
+
+static void
+logClose(struct _TServer * const srvP) {
+
+    if (srvP->logfileisopen) {
+        FileClose(&srvP->logfile);
+        MutexFree(&srvP->logmutex);
+        srvP->logfileisopen = FALSE;
+    }
+}
+
+
+
+static void
+initSocketStuff(struct _TServer * const srvP,
+                abyss_bool        const noAccept,
+                TSocket *         const userSocketP,
+                uint16_t          const port,
+                const char **     const errorP) {
+
+    if (userSocketP) {
+        *errorP = NULL;
+        srvP->serverAcceptsConnections = TRUE;
+        srvP->socketBound = TRUE;
+        srvP->listenSocketP = userSocketP;
+    } else if (noAccept) {
+        *errorP = NULL;
+        srvP->serverAcceptsConnections = FALSE;
+        srvP->socketBound = FALSE;
+    } else {
+        *errorP = NULL;
+        srvP->serverAcceptsConnections = TRUE;
+        srvP->socketBound = FALSE;
+        srvP->port = port;
+    }
+    srvP->weCreatedListenSocket = FALSE;
+}
+
+
+
+static void
+createServer(struct _TServer ** const srvPP,
+             abyss_bool         const noAccept,
+             TSocket *          const userSocketP,
+             uint16_t           const portNumber,             
+             const char **      const errorP) {
+
+    struct _TServer * srvP;
+
+    MALLOCVAR(srvP);
+
+    if (srvP == NULL) {
+        xmlrpc_asprintf(errorP,
+                        "Unable to allocate space for server descriptor");
+    } else {
+        srvP->terminationRequested = false;
+
+        initSocketStuff(srvP, noAccept, userSocketP, portNumber, errorP);
+
+        if (!*errorP) {
+            srvP->defaulthandler = ServerDefaultHandlerFunc;
+
+            srvP->name             = strdup("unnamed");
+            srvP->filespath        = strdup(DEFAULT_DOCS);
+            srvP->logfilename      = NULL;
+            srvP->keepalivetimeout = 15;
+            srvP->keepalivemaxconn = 30;
+            srvP->timeout          = 15;
+            srvP->advertise        = TRUE;
+            srvP->mimeTypeP        = NULL;
+            srvP->useSigchld       = FALSE;
+            
+            initUnixStuff(srvP);
+
+            ListInitAutoFree(&srvP->handlers);
+            ListInitAutoFree(&srvP->defaultfilenames);
+
+            srvP->logfileisopen = FALSE;
+
+            *errorP = NULL;
+        }        
+        if (*errorP)
+            free(srvP);
+    }
+    *srvPP = srvP;
+}
+
+
+
+static void
+setNamePathLog(TServer *    const serverP,
+               const char * const name,
+               const char * const filesPath,
+               const char * const logFileName) {
+/*----------------------------------------------------------------------------
+   This odd function exists to help with backward compatibility.
+   Today, we have the expandable model where you create a server with
+   default parameters, then use ServerSet... functions to choose
+   non-default parameters.  But before, you specified these three
+   parameters right in the arguments of various create functions.
+-----------------------------------------------------------------------------*/
+    if (name)
+        ServerSetName(serverP, name);
+    if (filesPath)
+        ServerSetFilesPath(serverP, filesPath);
+    if (logFileName)
+        ServerSetLogFileName(serverP, logFileName);
+}
+
+
+
+abyss_bool
+ServerCreate(TServer *    const serverP,
+             const char * const name,
+             uint16_t     const portNumber,
+             const char * const filesPath,
+             const char * const logFileName) {
+
+    abyss_bool const noAcceptFalse = FALSE;
+
+    abyss_bool success;
+    const char * error;
+
+    createServer(&serverP->srvP, noAcceptFalse, NULL, portNumber, &error);
+
+    if (error) {
+        TraceMsg(error);
+        xmlrpc_strfree(error);
+        success = FALSE;
+    } else {
+        success = TRUE;
+    
+        setNamePathLog(serverP, name, filesPath, logFileName);
+    }
+
+    return success;
+}
+
+
+
+static void
+createSocketFromOsSocket(TOsSocket    const osSocket,
+                         TSocket **   const socketPP) {
+
+#ifdef WIN32
+    SocketWinCreateWinsock(osSocket, socketPP);
+#else
+    SocketUnixCreateFd(osSocket, socketPP);
+#endif
+}
+
+
+
+abyss_bool
+ServerCreateSocket(TServer *    const serverP,
+                   const char * const name,
+                   TOsSocket    const socketFd,
+                   const char * const filesPath,
+                   const char * const logFileName) {
+
+    abyss_bool success;
+    TSocket * socketP;
+
+    createSocketFromOsSocket(socketFd, &socketP);
+
+    if (socketP) {
+        abyss_bool const noAcceptFalse = FALSE;
+
+        const char * error;
+
+        createServer(&serverP->srvP, noAcceptFalse, socketP, 0, &error);
+
+        if (error) {
+            TraceMsg(error);
+            success = FALSE;
+            xmlrpc_strfree(error);
+        } else {
+            success = TRUE;
+            
+            setNamePathLog(serverP, name, filesPath, logFileName);
+        }
+    } else
+        success = FALSE;
+
+    return success;
+}
+
+
+
+abyss_bool
+ServerCreateNoAccept(TServer *    const serverP,
+                     const char * const name,
+                     const char * const filesPath,
+                     const char * const logFileName) {
+
+    abyss_bool const noAcceptTrue = TRUE;
+
+    abyss_bool success;
+    const char * error;
+
+    createServer(&serverP->srvP, noAcceptTrue, NULL, 0, &error);
+
+    if (error) {
+        TraceMsg(error);
+        success = FALSE;
+        xmlrpc_strfree(error);
+    } else {
+        success = TRUE;
+        
+        setNamePathLog(serverP, name, filesPath, logFileName);
+    }
+    return success;
+}
+
+
+
+void
+ServerCreateSocket2(TServer *     const serverP,
+                    TSocket *     const socketP,
+                    const char ** const errorP) {
+    
+    abyss_bool const noAcceptFalse = FALSE;
+
+    assert(socketP);
+
+    createServer(&serverP->srvP, noAcceptFalse, socketP, 0, errorP);
+}
+
+
+
+static void
+terminateHandlers(TList * const handlersP) {
+/*----------------------------------------------------------------------------
+   Terminate all handlers in the list '*handlersP'.
+
+   I.e. call each handler's terminate function.
+-----------------------------------------------------------------------------*/
+    if (handlersP->item) {
+        unsigned int i;
+        for (i = handlersP->size; i > 0; --i) {
+            URIHandler2 * const handlerP = handlersP->item[i-1];
+            if (handlerP->term)
+                handlerP->term(handlerP->userdata);
+        }
+    }
+}
+
+
+
+void
+ServerFree(TServer * const serverP) {
+
+    struct _TServer * const srvP = serverP->srvP;
+
+    if (srvP->weCreatedListenSocket)
+        SocketDestroy(srvP->listenSocketP);
+
+    xmlrpc_strfree(srvP->name);
+
+    xmlrpc_strfree(srvP->filespath);
+    
+    ListFree(&srvP->defaultfilenames);
+
+    terminateHandlers(&srvP->handlers);
+
+    ListFree(&srvP->handlers);
+
+    logClose(srvP);
+
+    if (srvP->logfilename)
+        xmlrpc_strfree(srvP->logfilename);
+
+    free(srvP);
+}
+
+
+
+void
+ServerSetName(TServer *    const serverP,
+              const char * const name) {
+
+    xmlrpc_strfree(serverP->srvP->name);
+    
+    serverP->srvP->name = strdup(name);
+}
+
+
+
+void
+ServerSetFilesPath(TServer *    const serverP,
+                   const char * const filesPath) {
+
+    xmlrpc_strfree(serverP->srvP->filespath);
+    
+    serverP->srvP->filespath = strdup(filesPath);
+}
+
+
+
+void
+ServerSetLogFileName(TServer *    const serverP,
+                     const char * const logFileName) {
+    
+    struct _TServer * const srvP = serverP->srvP;
+
+    if (srvP->logfilename)
+        xmlrpc_strfree(srvP->logfilename);
+    
+    srvP->logfilename = strdup(logFileName);
+}
+
+
+
+void
+ServerSetKeepaliveTimeout(TServer * const serverP,
+                          uint32_t  const keepaliveTimeout) {
+
+    serverP->srvP->keepalivetimeout = keepaliveTimeout;
+}
+
+
+
+void
+ServerSetKeepaliveMaxConn(TServer * const serverP,
+                          uint32_t  const keepaliveMaxConn) {
+
+    serverP->srvP->keepalivemaxconn = keepaliveMaxConn;
+}
+
+
+
+void
+ServerSetTimeout(TServer * const serverP,
+                 uint32_t  const timeout) {
+
+    serverP->srvP->timeout = timeout;
+}
+
+
+
+void
+ServerSetAdvertise(TServer *  const serverP,
+                   abyss_bool const advertise) {
+
+    serverP->srvP->advertise = advertise;
+}
+
+
+
+void
+ServerSetMimeType(TServer *  const serverP,
+                  MIMEType * const MIMETypeP) {
+
+    serverP->srvP->mimeTypeP = MIMETypeP;
+}
+
+
+
+static void
+runUserHandler(TSession *        const sessionP,
+               struct _TServer * const srvP) {
+
+    abyss_bool handled;
+    int i;
+    
+    for (i = srvP->handlers.size-1, handled = FALSE;
+         i >= 0 && !handled;
+         --i) {
+        URIHandler2 * const handlerP = srvP->handlers.item[i];
+        
+        if (handlerP->handleReq2)
+            handlerP->handleReq2(handlerP, sessionP, &handled);
+        else if (handlerP->handleReq1)
+            handled = handlerP->handleReq1(sessionP);
+    }
+    
+    if (!handled)
+        ((URIHandler)(srvP->defaulthandler))(sessionP);
+}
+
+
+
+static void
+processDataFromClient(TConn *      const connectionP,
+                      abyss_bool   const lastReqOnConn,
+                      abyss_bool * const keepAliveP) {
+
+    TSession session;
+
+    RequestInit(&session, connectionP);
+
+    session.serverDeniesKeepalive = lastReqOnConn;
+        
+    RequestRead(&session);
+    if (session.status == 0) {
+        if (session.version.major >= 2)
+            ResponseStatus(&session, 505);
+        else if (!RequestValidURI(&session))
+            ResponseStatus(&session, 400);
+        else
+            runUserHandler(&session, connectionP->server->srvP);
+    }
+    assert(session.status != 0);
+    
+    if (session.responseStarted)
+        HTTPWriteEndChunk(&session);
+    else
+        ResponseError(&session);
+
+    *keepAliveP = HTTPKeepalive(&session);
+    
+    SessionLog(&session);
+
+    RequestFree(&session);
+}
+
+
+static TThreadProc serverFunc;
+
+static void
+serverFunc(void * const userHandle) {
+/*----------------------------------------------------------------------------
+   Do server stuff on one connection.  At its simplest, this means do
+   one HTTP request.  But with keepalive, it can be many requests.
+-----------------------------------------------------------------------------*/
+    TConn *           const connectionP = userHandle;
+    struct _TServer * const srvP = connectionP->server->srvP;
+
+    unsigned int requestCount;
+        /* Number of requests we've handled so far on this connection */
+    abyss_bool connectionDone;
+        /* No more need for this HTTP connection */
+
+    requestCount = 0;
+    connectionDone = FALSE;
+
+    while (!connectionDone) {
+        abyss_bool success;
+        
+        /* Wait to read until timeout */
+        success = ConnRead(connectionP, srvP->keepalivetimeout);
+
+        if (!success)
+            connectionDone = TRUE;
+        else {
+            abyss_bool const lastReqOnConn =
+                requestCount + 1 >= srvP->keepalivemaxconn;
+
+            abyss_bool keepalive;
+            
+            processDataFromClient(connectionP, lastReqOnConn, &keepalive);
+            
+            ++requestCount;
+
+            if (!keepalive)
+                connectionDone = TRUE;
+            
+            /**************** Must adjust the read buffer *****************/
+            ConnReadInit(connectionP);
+        }
+    }
+}
+
+
+
+static void
+createAndBindSocket(struct _TServer * const srvP) {
+
+    abyss_bool success;
+
+    success = SocketInit();
+    if (!success)
+        TraceMsg("Can't initialize TCP sockets");
+    else {
+        TSocket * socketP;
+        
+        SocketUnixCreate(&socketP);
+        
+        if (!socketP)
+            TraceMsg("Can't create a socket");
+        else {
+            abyss_bool success;
+            
+            success = SocketBind(socketP, NULL, srvP->port);
+            
+            if (!success)
+                TraceMsg("Failed to bind listening socket to port number %u",
+                         srvP->port);
+            else {
+                srvP->weCreatedListenSocket = TRUE;
+                srvP->socketBound = TRUE;
+                srvP->listenSocketP = socketP;
+            }
+            if (!success)
+                SocketDestroy(socketP);
+        }
+    }
+}
+
+
+
+void
+ServerInit(TServer * const serverP) {
+/*----------------------------------------------------------------------------
+   Initialize a server to accept connections.
+
+   Do not confuse this with creating the server -- ServerCreate().
+
+   Not necessary or valid with a server that doesn't accept connections (i.e.
+   user supplies the TCP connections).
+-----------------------------------------------------------------------------*/
+    struct _TServer * const srvP = serverP->srvP;
+    abyss_bool success;
+    
+    if (!srvP->serverAcceptsConnections) {
+        TraceMsg("ServerInit() is not valid on a server that doesn't "
+                 "accept connections "
+                 "(i.e. created with ServerCreateNoAccept)");
+        success = FALSE;
+    } else {
+        if (!srvP->socketBound)
+            createAndBindSocket(srvP);
+
+        if (srvP->socketBound) {
+            success = SocketListen(srvP->listenSocketP, MAX_CONN);
+
+            if (!success)
+                TraceMsg("Failed to listen on bound socket.");
+        } else
+            success = FALSE;
+    }
+    if (!success)
+        exit(1);
+}
+
+
+
+/* We don't do any locking on the outstanding connections list, so 
+   we must make sure that only the master thread (the one that listens
+   for connections) ever accesses it.
+
+   That's why when a thread completes, it places the connection in
+   "finished" status, but doesn't destroy the connection.
+*/
+
+typedef struct {
+
+    TConn * firstP;
+    unsigned int count;
+        /* Redundant with 'firstP', for quick access */
+} outstandingConnList;
+
+
+
+static void
+createOutstandingConnList(outstandingConnList ** const listPP) {
+
+    outstandingConnList * listP;
+
+    MALLOCVAR_NOFAIL(listP);
+
+    listP->firstP = NULL;  /* empty list */
+    listP->count = 0;
+
+    *listPP = listP;
+}
+
+
+
+static void
+destroyOutstandingConnList(outstandingConnList * const listP) {
+
+    assert(listP->firstP == NULL);
+    assert(listP->count == 0);
+
+    free(listP);
+}
+
+
+
+static void
+addToOutstandingConnList(outstandingConnList * const listP,
+                         TConn *               const connectionP) {
+
+    connectionP->nextOutstandingP = listP->firstP;
+
+    listP->firstP = connectionP;
+
+    ++listP->count;
+}
+
+
+
+static void
+freeFinishedConns(outstandingConnList * const listP) {
+/*----------------------------------------------------------------------------
+   Garbage-collect the resources associated with connections that are
+   finished with their jobs.  Thread resources, connection pool
+   descriptor, etc.
+-----------------------------------------------------------------------------*/
+    TConn ** pp;
+
+    pp = &listP->firstP;
+
+    while (*pp) {
+        TConn * const connectionP = (*pp);
+
+        ThreadUpdateStatus(connectionP->threadP);
+        
+        if (connectionP->finished) {
+            /* Take it out of the list */
+            *pp = connectionP->nextOutstandingP;
+            --listP->count;
+            
+            ConnWaitAndRelease(connectionP);
+        } else {
+            /* Move to next connection in list */
+            pp = &connectionP->nextOutstandingP;
+        }
+    }
+}
+
+
+
+static void
+waitForConnectionFreed(outstandingConnList * const outstandingConnListP
+                       ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+  Wait for a connection descriptor in 'connectionPool' to be probably
+  freed.
+-----------------------------------------------------------------------------*/
+
+    /* TODO: We should do something more sophisticated here.  For pthreads,
+       we can have a thread signal us by semaphore when it terminates.
+       For fork, we might be able to use the "done" handler argument
+       to ConnCreate() to get interrupted when the death of a child
+       signal happens.
+    */
+
+    xmlrpc_millisecond_sleep(2000);
+}
+
+
+
+static void
+waitForNoConnections(outstandingConnList * const outstandingConnListP) {
+
+    while (outstandingConnListP->firstP) {
+        freeFinishedConns(outstandingConnListP);
+    
+        if (outstandingConnListP->firstP)
+            waitForConnectionFreed(outstandingConnListP);
+    }
+}
+
+
+
+static void
+waitForConnectionCapacity(outstandingConnList * const outstandingConnListP) {
+/*----------------------------------------------------------------------------
+   Wait until there are fewer than the maximum allowed connections in
+   progress.
+-----------------------------------------------------------------------------*/
+    while (outstandingConnListP->count >= MAX_CONN) {
+        freeFinishedConns(outstandingConnListP);
+        if (outstandingConnListP->firstP)
+            waitForConnectionFreed(outstandingConnListP);
+    }
+}
+
+
+
+#ifndef WIN32
+void
+ServerHandleSigchld(pid_t const pid) {
+
+    ThreadHandleSigchld(pid);
+}
+#endif
+
+
+
+void
+ServerUseSigchld(TServer * const serverP) {
+
+    struct _TServer * const srvP = serverP->srvP;
+    
+    srvP->useSigchld = TRUE;
+}
+
+
+
+TThreadDoneFn destroySocket;
+
+static void
+destroyConnSocket(void * const userHandle) {
+/*----------------------------------------------------------------------------
+   This is a "connection done" function for the connection the server
+   serves.  It gets called some time after the connection has done its
+   thing.  Its job is to clean up stuff the server created for use by
+   the connection, but the server can't clean up because the
+   connection might be processed asynchronously in a background
+   thread.
+
+   To wit, we destroy the connection's socket.
+-----------------------------------------------------------------------------*/
+    TConn * const connectionP = userHandle;
+
+    SocketDestroy(connectionP->socketP);
+}
+
+
+
+static void 
+serverRun2(TServer * const serverP) {
+
+    struct _TServer * const srvP = serverP->srvP;
+    outstandingConnList * outstandingConnListP;
+
+    createOutstandingConnList(&outstandingConnListP);
+
+    while (!srvP->terminationRequested) {
+        TConn * connectionP;
+
+        abyss_bool connected;
+        abyss_bool failed;
+        TSocket * connectedSocketP;
+        TIPAddr peerIpAddr;
+
+        SocketAccept(srvP->listenSocketP,
+                     &connected, &failed,
+                     &connectedSocketP, &peerIpAddr);
+        
+        if (connected) {
+            const char * error;
+
+            freeFinishedConns(outstandingConnListP);
+
+            waitForConnectionCapacity(outstandingConnListP);
+
+            ConnCreate(&connectionP, serverP, connectedSocketP,
+                       &serverFunc, &destroyConnSocket, ABYSS_BACKGROUND,
+                       srvP->useSigchld,
+                       &error);
+            if (!error) {
+                addToOutstandingConnList(outstandingConnListP, connectionP);
+                ConnProcess(connectionP);
+                /* When connection is done (which could be later, courtesy
+                   of a background thread), destroyConnSocket() will
+                   destroy *connectedSocketP.
+                */
+            } else {
+                xmlrpc_strfree(error);
+                SocketDestroy(connectedSocketP);
+            }
+        } else if (failed)
+            TraceMsg("Socket Error=%d", SocketError(srvP->listenSocketP));
+    }
+    waitForNoConnections(outstandingConnListP);
+
+    destroyOutstandingConnList(outstandingConnListP);
+}
+
+
+
+void 
+ServerRun(TServer * const serverP) {
+
+    struct _TServer * const srvP = serverP->srvP;
+
+    if (!srvP->socketBound)
+        TraceMsg("This server is not set up to accept connections "
+                 "on its own, so you can't use ServerRun().  "
+                 "Try ServerRunConn() or ServerInit()");
+    else
+        serverRun2(serverP);
+}
+
+
+
+static void
+serverRunConn(TServer * const serverP,
+              TSocket * const connectedSocketP) {
+/*----------------------------------------------------------------------------
+   Do the HTTP transaction on the TCP connection on the socket
+   'connectedSocketP'.
+   (socket must be in connected state, with nothing having been read or
+   written on the connection yet).
+-----------------------------------------------------------------------------*/
+    struct _TServer * const srvP = serverP->srvP;
+
+    TConn * connectionP;
+    const char * error;
+
+    srvP->keepalivemaxconn = 1;
+
+    ConnCreate(&connectionP, 
+               serverP, connectedSocketP,
+               &serverFunc, NULL, ABYSS_FOREGROUND, srvP->useSigchld,
+               &error);
+    if (error) {
+        TraceMsg("Couldn't create HTTP connection out of "
+                 "connected socket.  %s", error);
+        xmlrpc_strfree(error);
+    } else {
+        ConnProcess(connectionP);
+
+        ConnWaitAndRelease(connectionP);
+    }
+}
+
+
+
+void
+ServerRunConn2(TServer *     const serverP,
+               TSocket *     const connectedSocketP,
+               const char ** const errorP) {
+/*----------------------------------------------------------------------------
+   Do the HTTP transaction on the TCP connection on the socket
+   'connectedOsSocket'.
+   (socket must be connected state, with nothing having been read or
+   written on the connection yet).
+-----------------------------------------------------------------------------*/
+    struct _TServer * const srvP = serverP->srvP;
+
+    if (srvP->serverAcceptsConnections)
+        xmlrpc_asprintf(errorP,
+                        "This server is configured to accept connections on "
+                        "its own socket.  "
+                        "Try ServerRun() or ServerCreateNoAccept().");
+    else {
+        serverRunConn(serverP, connectedSocketP);
+        *errorP = NULL;
+    }
+}
+
+
+
+void
+ServerRunConn(TServer * const serverP,
+              TOsSocket const connectedOsSocket) {
+
+    TSocket * socketP;
+    createSocketFromOsSocket(connectedOsSocket, &socketP);
+    if (!socketP)
+        TraceExit("Unable to use supplied socket");
+    else {
+        const char * error;
+
+        ServerRunConn2(serverP, socketP, &error);
+
+        if (error) {
+            TraceExit("Failed to run server on connection on file "
+                      "descriptor %d.  %s", connectedOsSocket, error);
+            xmlrpc_strfree(error);
+        }
+        SocketDestroy(socketP);
+    }
+}
+
+
+
+void
+ServerRunOnce(TServer * const serverP) {
+/*----------------------------------------------------------------------------
+   Accept a connection from the listening socket and do the HTTP
+   transaction that comes over it.
+
+   If no connection is presently waiting on the listening socket, wait
+   for one.  But return immediately if we receive a signal during the
+   wait.
+-----------------------------------------------------------------------------*/
+    struct _TServer * const srvP = serverP->srvP;
+
+    if (!srvP->socketBound)
+        TraceMsg("This server is not set up to accept connections "
+                 "on its own, so you can't use ServerRunOnce().  "
+                 "Try ServerRunConn() or ServerInit()");
+    else {
+        abyss_bool connected;
+        abyss_bool failed;
+        TSocket *  connectedSocketP;
+        TIPAddr    remoteAddr;
+    
+        srvP->keepalivemaxconn = 1;
+
+        SocketAccept(srvP->listenSocketP,
+                     &connected, &failed,
+                     &connectedSocketP, &remoteAddr);
+        if (connected) {
+            serverRunConn(serverP, connectedSocketP);
+            SocketDestroy(connectedSocketP);
+        } else if (failed)
+            TraceMsg("Socket Error=%d", SocketError(srvP->listenSocketP));
+    }
+}
+
+
+
+void
+ServerRunOnce2(TServer *           const serverP,
+               enum abyss_foreback const foregroundBackground ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+   This is a backward compatibility interface to ServerRunOnce().
+
+   'foregroundBackground' is meaningless.  We always process the
+   connection in the foreground.  The parameter exists because we once
+   thought we could do them in the background, but we really can't do
+   that in any clean way.  If Caller wants background execution, he can
+   spin his own thread or process to call us.  It makes much more sense
+   in Caller's context.
+-----------------------------------------------------------------------------*/
+    ServerRunOnce(serverP);
+}
+
+
+
+static void
+setGroups(void) {
+
+#ifdef HAVE_SETGROUPS   
+    if (setgroups(0, NULL) == (-1))
+        TraceExit("Failed to setup the group.");
+#endif
+}
+
+
+
+void
+ServerDaemonize(TServer * const serverP) {
+/*----------------------------------------------------------------------------
+   Turn Caller into a daemon (i.e. fork a child, then exit; the child
+   returns to Caller).
+
+   NOTE: It's ridiculous, but conventional, for us to do this.  It's
+   ridiculous because the task of daemonizing is not something
+   particular to Abyss.  It ought to be done by a higher level.  In
+   fact, it should be done before the Abyss server program is even
+   execed.  The user should run a "daemonize" program that creates a
+   daemon which execs the Abyss server program.
+-----------------------------------------------------------------------------*/
+    struct _TServer * const srvP = serverP->srvP;
+
+#ifndef _WIN32
+    /* Become a daemon */
+    switch (fork()) {
+    case 0:
+        break;
+    case -1:
+        TraceExit("Unable to become a daemon");
+    default:
+        /* We are the parent */
+        exit(0);
+    }
+    
+    setsid();
+
+    /* Change the current user if we are root */
+    if (getuid()==0) {
+        if (srvP->uid == (uid_t)-1)
+            TraceExit("Can't run under root privileges.  "
+                      "Please add a User option in your "
+                      "Abyss configuration file.");
+
+        setGroups();
+
+        if (srvP->gid != (gid_t)-1)
+            if (setgid(srvP->gid)==(-1))
+                TraceExit("Failed to change the group.");
+        
+        if (setuid(srvP->uid) == -1)
+            TraceExit("Failed to change the user.");
+    }
+    
+    if (srvP->pidfile != -1) {
+        char z[16];
+    
+        sprintf(z, "%d", getpid());
+        FileWrite(&srvP->pidfile, z, strlen(z));
+        FileClose(&srvP->pidfile);
+    }
+#endif  /* _WIN32 */
+}
+
+
+
+void
+ServerAddHandler2(TServer *     const serverP,
+                  URIHandler2 * const handlerArgP,
+                  abyss_bool *  const successP) {
+
+    URIHandler2 * handlerP;
+
+    MALLOCVAR(handlerP);
+    if (handlerP == NULL)
+        *successP = FALSE;
+    else {
+        *handlerP = *handlerArgP;
+
+        if (handlerP->init == NULL)
+            *successP = TRUE;
+        else
+            handlerP->init(handlerP, successP);
+
+        if (*successP)
+            *successP = ListAdd(&serverP->srvP->handlers, handlerP);
+
+        if (!*successP)
+            free(handlerP);
+    }
+}
+
+
+
+static URIHandler2 *
+createHandler(URIHandler const function) {
+
+    URIHandler2 * handlerP;
+
+    MALLOCVAR(handlerP);
+    if (handlerP != NULL) {
+        handlerP->init       = NULL;
+        handlerP->term       = NULL;
+        handlerP->userdata   = NULL;
+        handlerP->handleReq2 = NULL;
+        handlerP->handleReq1 = function;
+    }
+    return handlerP;
+}
+
+
+
+abyss_bool
+ServerAddHandler(TServer *  const serverP,
+                 URIHandler const function) {
+
+    URIHandler2 * handlerP;
+    abyss_bool success;
+
+    handlerP = createHandler(function);
+
+    if (handlerP == NULL)
+        success = FALSE;
+    else {
+        success = ListAdd(&serverP->srvP->handlers, handlerP);
+
+        if (!success)
+            free(handlerP);
+    }
+    return success;
+}
+
+
+
+void
+ServerDefaultHandler(TServer *  const serverP,
+                     URIHandler const handler) {
+
+    serverP->srvP->defaulthandler =
+        handler ? handler : ServerDefaultHandlerFunc;
+}
+
+
+
+void
+LogWrite(TServer *    const serverP,
+         const char * const msg) {
+
+    struct _TServer * const srvP = serverP->srvP;
+
+    if (!srvP->logfileisopen && srvP->logfilename)
+        logOpen(srvP);
+
+    if (srvP->logfileisopen) {
+        abyss_bool success;
+        success = MutexLock(&srvP->logmutex);
+        if (success) {
+            const char * const lbr = "\n";
+            FileWrite(&srvP->logfile, msg, strlen(msg));
+            FileWrite(&srvP->logfile, lbr, strlen(lbr));
+        
+            MutexUnlock(&srvP->logmutex);
+        }
+    }
+}
+/*******************************************************************************
+**
+** server.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
diff --git a/lib/abyss/src/server.h b/lib/abyss/src/server.h
new file mode 100644 (file)
index 0000000..db8bc79
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef SERVER_H_INCLUDED
+#define SERVER_H_INCLUDED
+
+#include <sys/types.h>
+
+#include "xmlrpc-c/abyss.h"
+
+#include "file.h"
+#include "data.h"
+
+typedef struct _Tsocket Tsocket;
+
+struct _TServer {
+    abyss_bool terminationRequested;
+        /* User wants this server to terminate as soon as possible,
+           in particular before accepting any more connections and without
+           waiting for any.
+        */
+    abyss_bool socketBound;
+        /* The listening socket exists and is bound to a local address
+           (may already be listening as well)
+        */
+    TSocket * listenSocketP;
+        /* Meaningful only when 'socketBound' is true: file descriptor of
+           the listening socket ("listening socket" means socket for listening,
+           not a socket that is listening right now).
+        */
+    abyss_bool weCreatedListenSocket;
+        /* We created the listen socket (whose fd is 'listensock'), as
+           opposed to 1) User supplied it; or 2) there isn't one.
+        */
+    const char * logfilename;
+    abyss_bool logfileisopen;
+    TFile logfile;
+    TMutex logmutex;
+    const char * name;
+    const char * filespath;
+    abyss_bool serverAcceptsConnections;
+        /* We listen for and accept TCP connections for HTTP transactions.
+           (The alternative is the user supplies a TCP-connected socket
+           for each transaction)
+        */
+    uint16_t port;
+        /* Meaningful only when 'socketBound' is false: port number to which
+           we should bind the listening socket
+        */
+    uint32_t keepalivetimeout;
+    uint32_t keepalivemaxconn;
+    uint32_t timeout;
+        /* Maximum time in seconds the server will wait to read a header
+           or a data chunk from the socket.
+        */
+    TList handlers;
+    TList defaultfilenames;
+    void * defaulthandler;
+    abyss_bool advertise;
+    MIMEType * mimeTypeP;
+        /* NULL means to use the global MIMEType object */
+    abyss_bool useSigchld;
+        /* Meaningless if not using forking for threads.
+           TRUE means user will call ServerHandleSigchld to indicate that
+           a SIGCHLD signal was received, and server shall use that as its
+           indication that a child has died.  FALSE means server will not
+           be aware of SIGCHLD and will instead poll for existence of PIDs
+           to determine if a child has died.
+        */
+#ifndef WIN32
+    uid_t uid;
+    gid_t gid;
+    TFile pidfile;
+#endif
+};
+
+
+void
+ServerBackgroundProcessComplete(pid_t const pid);
+
+#endif
diff --git a/lib/abyss/src/session.c b/lib/abyss/src/session.c
new file mode 100644 (file)
index 0000000..093ea7a
--- /dev/null
@@ -0,0 +1,137 @@
+#include <assert.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+#include "server.h"
+#include "http.h"
+#include "conn.h"
+
+#include "session.h"
+
+
+
+abyss_bool
+SessionRefillBuffer(TSession * const sessionP) {
+/*----------------------------------------------------------------------------
+   Get the next chunk of HTTP request body from the connection into
+   the buffer.
+
+   I.e. read data from the socket.
+-----------------------------------------------------------------------------*/
+    struct _TServer * const srvP = sessionP->conn->server->srvP;
+    abyss_bool failed;
+
+    failed = FALSE;  /* initial value */
+            
+    /* Reset our read buffer & flush data from previous reads. */
+    ConnReadInit(sessionP->conn);
+
+    if (sessionP->continueRequired)
+        failed = !HTTPWriteContinue(sessionP);
+
+    if (!failed) {
+        sessionP->continueRequired = FALSE;
+
+        /* Read more network data into our buffer.  If we encounter a
+           timeout, exit immediately.  We're very forgiving about the
+           timeout here.  We allow a full timeout per network read, which
+           would allow somebody to keep a connection alive nearly
+           indefinitely.  But it's hard to do anything intelligent here
+           without very complicated code.
+        */
+        failed = !ConnRead(sessionP->conn, srvP->timeout);     
+    }
+    return !failed;
+}
+
+
+
+size_t
+SessionReadDataAvail(TSession * const sessionP) {
+
+    return sessionP->conn->buffersize - sessionP->conn->bufferpos;
+
+}
+
+
+
+void
+SessionGetReadData(TSession *    const sessionP, 
+                   size_t        const max, 
+                   const char ** const outStartP, 
+                   size_t *      const outLenP) {
+/*----------------------------------------------------------------------------
+   Extract some HTTP request body which the server has read and
+   buffered for the session.  Don't get or wait for any data that has
+   not yet arrived.  Do not return more than 'max'.
+
+   We return a pointer to the first byte as *outStartP, and the length in
+   bytes as *outLenP.  The memory pointed to belongs to the session.
+-----------------------------------------------------------------------------*/
+    uint32_t const bufferPos = sessionP->conn->bufferpos;
+
+    *outStartP = &sessionP->conn->buffer[bufferPos];
+
+    assert(bufferPos <= sessionP->conn->buffersize);
+
+    *outLenP = MIN(max, sessionP->conn->buffersize - bufferPos);
+
+    /* move pointer past the bytes we are returning */
+    sessionP->conn->bufferpos += *outLenP;
+
+    assert(sessionP->conn->bufferpos <= sessionP->conn->buffersize);
+}
+
+
+
+void
+SessionGetRequestInfo(TSession *            const sessionP,
+                      const TRequestInfo ** const requestInfoPP) {
+    
+    *requestInfoPP = &sessionP->request_info;
+}
+
+
+
+abyss_bool
+SessionLog(TSession * const sessionP) {
+
+    abyss_bool retval;
+
+    if (!sessionP->validRequest)
+        retval = FALSE;
+    else {
+        const char * const user = sessionP->request_info.user;
+
+        const char * logline;
+        char date[30];
+
+        DateToLogString(&sessionP->date, date);
+
+        xmlrpc_asprintf(&logline, "%d.%d.%d.%d - %s - [%s] \"%s\" %d %d",
+                        IPB1(sessionP->conn->peerip),
+                        IPB2(sessionP->conn->peerip),
+                        IPB3(sessionP->conn->peerip),
+                        IPB4(sessionP->conn->peerip),
+                        user ? user : "",
+                        date, 
+                        sessionP->request_info.requestline,
+                        sessionP->status,
+                        sessionP->conn->outbytes
+            );
+        if (logline) {
+            LogWrite(sessionP->conn->server, logline);
+
+            xmlrpc_strfree(logline);
+        }
+        retval = TRUE;
+    }
+    return retval;
+}
+
+
+
diff --git a/lib/abyss/src/session.h b/lib/abyss/src/session.h
new file mode 100644 (file)
index 0000000..43a5616
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef SESSION_H_INCLUDED
+#define SESSION_H_INCLUDED
+
+#include "xmlrpc-c/abyss.h"
+#include "date.h"
+#include "data.h"
+
+typedef struct {
+    uint8_t major;
+    uint8_t minor;
+} httpVersion;
+
+struct _TSession {
+    abyss_bool validRequest;
+        /* Client has sent, and server has recognized, a valid HTTP request.
+           This is false when the session is new.  If and when the server
+           reads the request from the client and finds it to be valid HTTP,
+           it becomes true.
+        */
+    TRequestInfo request_info;
+    uint32_t nbfileds;
+    TList cookies;
+    TList ranges;
+
+    uint16_t status;
+        /* Response status from handler.  Zero means handler has not
+           set it.
+        */
+    TString header;
+
+    abyss_bool serverDeniesKeepalive;
+        /* Server doesn't want keepalive for this session, regardless of
+           what happens in the session.  E.g. because the connection has
+           already been kept alive long enough.
+        */
+    abyss_bool responseStarted;
+        /* Handler has at least started the response (i.e. called
+           ResponseWrite())
+        */
+
+    struct _TConn * conn;
+
+    httpVersion version;
+
+    TTable request_headers;
+    TTable response_headers;
+
+    TDate date;
+
+    abyss_bool chunkedwrite;
+    abyss_bool chunkedwritemode;
+
+    abyss_bool continueRequired;
+        /* This client must receive 100 (continue) status before it will
+           send more of the body of the request.
+        */
+};
+
+
+#endif
diff --git a/lib/abyss/src/socket.c b/lib/abyss/src/socket.c
new file mode 100644 (file)
index 0000000..7868542
--- /dev/null
@@ -0,0 +1,230 @@
+/*============================================================================
+  socket.c
+==============================================================================
+  Implementation of TSocket class: A generic socket over which one can
+  transport an HTTP stream or manage HTTP connections
+============================================================================*/
+
+#include <sys/types.h>
+#include <assert.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mallocvar.h"
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/abyss.h"
+#include "xmlrpc-c/util_int.h"
+#ifdef WIN32
+  #include "socket_win.h"
+#else
+  #include "socket_unix.h"
+#endif
+#include "socket.h"
+
+
+#ifdef WIN32
+  #include "socket_win.h"
+#else
+  #include "socket_unix.h"
+#endif
+
+#include "socket.h"
+
+
+static void
+socketOsInit(abyss_bool * const succeededP) {
+
+#ifdef WIN32
+    SocketWinInit(succeededP);
+#else
+    SocketUnixInit(succeededP);
+#endif
+}
+
+
+
+static void
+socketOsTerm(void) {
+
+#ifdef WIN32
+    SocketWinTerm();
+#else
+    SocketUnixTerm();
+#endif
+}
+    
+
+
+abyss_bool SocketTraceIsActive;
+
+abyss_bool
+SocketInit(void) {
+    abyss_bool retval;
+
+    socketOsInit(&retval);
+
+    SocketTraceIsActive = (getenv("ABYSS_TRACE_SOCKET") != NULL);
+    if (SocketTraceIsActive)
+        fprintf(stderr, "Abyss socket layer will trace socket traffic "
+                "due to ABYSS_TRACE_SOCKET environment variable\n");
+
+    return retval;
+}
+
+
+
+void
+SocketTerm(void) {
+
+    socketOsTerm();
+}
+
+
+
+/* SocketCreate() is not exported to the Abyss user.  It is meant to
+   be used by an implementation-specific TSocket generator which is
+   exported to the Abyss user, e.g. SocketCreateUnix() in
+   socket_unix.c
+
+   The TSocket generator functions are the _only_ user-accessible
+   functions that are particular to an implementation.
+*/
+
+static uint const socketSignature = 0x060609;
+
+void
+SocketCreate(const struct TSocketVtbl * const vtblP,
+             void *                     const implP,
+             TSocket **                 const socketPP) {
+
+    TSocket * socketP;
+
+    MALLOCVAR(socketP);
+
+    if (socketP) {
+        socketP->implP = implP;
+        socketP->vtbl = *vtblP;
+        socketP->signature = socketSignature;
+        *socketPP = socketP;
+    }
+}
+
+
+
+void
+SocketDestroy(TSocket * const socketP) {
+
+    assert(socketP->signature == socketSignature);
+
+    socketP->vtbl.destroy(socketP);
+
+    socketP->signature = 0;  /* For debuggability */
+
+    free(socketP);
+}
+
+
+
+void
+SocketWrite(TSocket *             const socketP,
+            const unsigned char * const buffer,
+            uint32_t              const len,
+            abyss_bool *          const failedP) {
+
+    (*socketP->vtbl.write)(socketP, buffer, len, failedP );
+}
+
+
+
+uint32_t
+SocketRead(TSocket *       const socketP, 
+           unsigned char * const buffer, 
+           uint32_t        const len) {
+    
+    return (*socketP->vtbl.read)(socketP, buffer, len);
+}
+
+
+
+abyss_bool
+SocketConnect(TSocket * const socketP,
+              TIPAddr * const addrP,
+              uint16_t  const portNumber) {
+
+    return (*socketP->vtbl.connect)(socketP, addrP, portNumber);
+}
+
+
+
+abyss_bool
+SocketBind(TSocket * const socketP,
+           TIPAddr * const addrP,
+           uint16_t  const portNumber) {
+
+    return (*socketP->vtbl.bind)(socketP, addrP, portNumber);
+}
+
+
+
+abyss_bool
+SocketListen(TSocket * const socketP,
+             uint32_t  const backlog) {
+
+    return (*socketP->vtbl.listen)(socketP, backlog);
+}
+
+
+
+void
+SocketAccept(TSocket *    const listenSocketP,
+             abyss_bool * const connectedP,
+             abyss_bool * const failedP,
+             TSocket **   const acceptedSocketPP,
+             TIPAddr *    const ipAddrP) {
+
+    (*listenSocketP->vtbl.accept)(listenSocketP,
+                                  connectedP,
+                                  failedP,
+                                  acceptedSocketPP,
+                                  ipAddrP);
+}
+
+
+
+uint32_t
+SocketWait(TSocket *  const socketP,
+           abyss_bool const rd,
+           abyss_bool const wr,
+           uint32_t   const timems) {
+
+    return (*socketP->vtbl.wait)(socketP, rd, wr, timems);
+}
+
+
+
+uint32_t
+SocketAvailableReadBytes(TSocket * const socketP) {
+
+    return (*socketP->vtbl.availableReadBytes)(socketP);
+}
+
+
+
+void
+SocketGetPeerName(TSocket *    const socketP,
+                  TIPAddr *    const ipAddrP,
+                  uint16_t *   const portNumberP,
+                  abyss_bool * const successP) {
+
+    (*socketP->vtbl.getPeerName)(socketP, ipAddrP, portNumberP, successP);
+}
+
+
+
+uint32_t
+SocketError(TSocket * const socketP) {
+
+    return (*socketP->vtbl.error)(socketP);
+}
diff --git a/lib/abyss/src/socket.h b/lib/abyss/src/socket.h
new file mode 100644 (file)
index 0000000..fd8c4b8
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef SOCKET_H_INCLUDED
+#define SOCKET_H_INCLUDED
+
+#include <netinet/in.h>
+
+#include "xmlrpc-c/abyss.h"
+
+#include <netinet/in.h>
+
+#define IPB1(x) (((unsigned char *)(&x))[0])
+#define IPB2(x) (((unsigned char *)(&x))[1])
+#define IPB3(x) (((unsigned char *)(&x))[2])
+#define IPB4(x) (((unsigned char *)(&x))[3])
+
+typedef struct in_addr TIPAddr;
+
+typedef void SocketDestroyImpl(TSocket * const socketP);
+
+typedef void SocketWriteImpl(TSocket *             const socketP,
+                             const unsigned char * const buffer,
+                             uint32_t              const len,
+                             abyss_bool *          const failedP);
+
+typedef uint32_t SocketReadImpl(TSocket * const socketP,
+                                char *    const buffer,
+                                uint32_t  const len);
+
+typedef abyss_bool SocketConnectImpl(TSocket * const socketP,
+                                     TIPAddr * const addrP,
+                                     uint16_t  const portNumber);
+
+typedef abyss_bool SocketBindImpl(TSocket * const socketP,
+                                  TIPAddr * const addrP,
+                                  uint16_t  const portNumber);
+
+typedef abyss_bool SocketListenImpl(TSocket * const socketP,
+                                    uint32_t  const backlog);
+
+typedef void SocketAcceptImpl(TSocket *    const listenSocketP,
+                              abyss_bool * const connectedP,
+                              abyss_bool * const failedP,
+                              TSocket **   const acceptedSocketPP,
+                              TIPAddr *    const ipAddrP);
+
+typedef uint32_t SocketErrorImpl(TSocket * const socketP);
+
+typedef uint32_t SocketWaitImpl(TSocket *  const socketP,
+                                abyss_bool const rd,
+                                abyss_bool const wr,
+                                uint32_t   const timems);
+
+typedef uint32_t SocketAvailableReadBytesImpl(TSocket * const socketP);
+
+typedef void SocketGetPeerNameImpl(TSocket *    const socketP,
+                                   TIPAddr *    const ipAddrP,
+                                   uint16_t *   const portNumberP,
+                                   abyss_bool * const successP);
+
+struct TSocketVtbl {
+    SocketDestroyImpl            * destroy;
+    SocketWriteImpl              * write;
+    SocketReadImpl               * read;
+    SocketConnectImpl            * connect;
+    SocketBindImpl               * bind;
+    SocketListenImpl             * listen;
+    SocketAcceptImpl             * accept;
+    SocketErrorImpl              * error;
+    SocketWaitImpl               * wait;
+    SocketAvailableReadBytesImpl * availableReadBytes;
+    SocketGetPeerNameImpl        * getPeerName;
+};
+
+struct _TSocket {
+    uint               signature;
+        /* With both background and foreground use of sockets, and
+           background being both fork and pthread, it is very easy to
+           screw up socket lifetime and try to destroy twice.  We use
+           this signature to help catch such bugs.
+        */
+    void *             implP;
+    struct TSocketVtbl vtbl;
+};
+
+#define TIME_INFINITE   0xffffffff
+
+extern abyss_bool SocketTraceIsActive;
+
+abyss_bool
+SocketInit(void);
+
+void
+SocketTerm(void);
+
+void
+SocketCreate(const struct TSocketVtbl * const vtblP,
+             void *                     const implP,
+             TSocket **                 const socketPP);
+
+void
+SocketWrite(TSocket *             const socketP,
+            const unsigned char * const buffer,
+            uint32_t              const len,
+            abyss_bool *          const failedP);
+
+uint32_t
+SocketRead(TSocket *       const socketP, 
+           unsigned char * const buffer, 
+           uint32_t        const len);
+
+abyss_bool
+SocketConnect(TSocket * const socketP,
+              TIPAddr * const addrP,
+              uint16_t  const portNumber);
+
+abyss_bool
+SocketBind(TSocket * const socketP,
+           TIPAddr * const addrP,
+           uint16_t  const portNumber);
+
+abyss_bool
+SocketListen(TSocket * const socketP,
+             uint32_t  const backlog);
+
+void
+SocketAccept(TSocket *    const listenSocketP,
+             abyss_bool * const connectedP,
+             abyss_bool * const failedP,
+             TSocket **   const acceptedSocketP,
+             TIPAddr *    const ipAddrP);
+
+uint32_t
+SocketWait(TSocket *  const socketP,
+           abyss_bool const rd,
+           abyss_bool const wr,
+           uint32_t   const timems);
+
+uint32_t
+SocketAvailableReadBytes(TSocket * const socketP);
+
+void
+SocketGetPeerName(TSocket *    const socketP,
+                  TIPAddr *    const ipAddrP,
+                  uint16_t *   const portNumberP,
+                  abyss_bool * const successP);
+
+uint32_t
+SocketError(TSocket * const socketP);
+
+#endif
diff --git a/lib/abyss/src/socket_unix.c b/lib/abyss/src/socket_unix.c
new file mode 100644 (file)
index 0000000..3f425c9
--- /dev/null
@@ -0,0 +1,501 @@
+/*=============================================================================
+                                 socket_unix.c
+===============================================================================
+  This is the implementation of TSocket for a standard Unix (POSIX)
+  stream socket -- what you create with a socket() C library call.
+=============================================================================*/
+
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#if HAVE_SYS_FILIO_H
+  #include <sys/filio.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+  #include <sys/ioctl.h>
+#endif
+
+#include "xmlrpc-c/util_int.h"
+#include "mallocvar.h"
+#include "trace.h"
+#include "socket.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "socket_unix.h"
+
+
+
+struct socketUnix {
+/*----------------------------------------------------------------------------
+   The properties/state of a TSocket unique to a Unix TSocket.
+-----------------------------------------------------------------------------*/
+    int fd;
+        /* File descriptor of the POSIX socket (such as is created by
+           socket() in the C library) on which the TSocket is based.
+        */
+    abyss_bool userSuppliedFd;
+        /* The file descriptor and associated POSIX socket belong to the
+           user; we did not create it.
+        */
+};
+
+
+void
+SocketUnixInit(abyss_bool * const succeededP) {
+
+    *succeededP = TRUE;
+}
+
+
+
+void
+SocketUnixTerm(void) {
+
+}
+
+
+
+static SocketDestroyImpl            socketDestroy;
+static SocketWriteImpl              socketWrite;
+static SocketReadImpl               socketRead;
+static SocketConnectImpl            socketConnect;
+static SocketBindImpl               socketBind;
+static SocketListenImpl             socketListen;
+static SocketAcceptImpl             socketAccept;
+static SocketErrorImpl              socketError;
+static SocketWaitImpl               socketWait;
+static SocketAvailableReadBytesImpl socketAvailableReadBytes;
+static SocketGetPeerNameImpl        socketGetPeerName;
+
+
+static struct TSocketVtbl const vtbl = {
+    &socketDestroy,
+    &socketWrite,
+    &socketRead,
+    &socketConnect,
+    &socketBind,
+    &socketListen,
+    &socketAccept,
+    &socketError,
+    &socketWait,
+    &socketAvailableReadBytes,
+    &socketGetPeerName
+};
+
+
+
+void
+SocketUnixCreate(TSocket ** const socketPP) {
+
+    struct socketUnix * socketUnixP;
+
+    MALLOCVAR(socketUnixP);
+
+    if (socketUnixP) {
+        int rc;
+        rc = socket(AF_INET, SOCK_STREAM, 0);
+        if (rc < 0)
+            *socketPP = NULL;
+        else {
+            socketUnixP->fd = rc;
+            socketUnixP->userSuppliedFd = FALSE;
+            
+            {
+                int32_t n = 1;
+                int rc;
+                rc = setsockopt(socketUnixP->fd, SOL_SOCKET, SO_REUSEADDR,
+                                (char*)&n, sizeof(n));
+                if (rc < 0)
+                    *socketPP = NULL;
+                else
+                    SocketCreate(&vtbl, socketUnixP, socketPP);
+            }
+            if (!*socketPP)
+                close(socketUnixP->fd);
+        }
+        if (!*socketPP)
+            free(socketUnixP);
+    } else
+        *socketPP = NULL;
+}
+
+
+
+void
+SocketUnixCreateFd(int        const fd,
+                   TSocket ** const socketPP) {
+
+    struct socketUnix * socketUnixP;
+
+    MALLOCVAR(socketUnixP);
+
+    if (socketUnixP) {
+        socketUnixP->fd = fd;
+        socketUnixP->userSuppliedFd = TRUE;
+
+        SocketCreate(&vtbl, socketUnixP, socketPP);
+
+        if (!*socketPP)
+            free(socketUnixP);
+    } else
+        *socketPP = NULL;
+}
+
+
+
+static void
+socketDestroy(TSocket * const socketP) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    if (!socketUnixP->userSuppliedFd)
+        close(socketUnixP->fd);
+
+    free(socketUnixP);
+}
+
+
+
+static void
+socketWrite(TSocket *             const socketP,
+            const unsigned char * const buffer,
+            uint32_t              const len,
+            abyss_bool *          const failedP) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    size_t bytesLeft;
+    abyss_bool error;
+
+    assert(sizeof(size_t) >= sizeof(len));
+
+    for (bytesLeft = len, error = FALSE;
+         bytesLeft > 0 && !error;
+        ) {
+        size_t const maxSend = (size_t)(-1) >> 1;
+
+        ssize_t rc;
+        
+        rc = send(socketUnixP->fd, &buffer[len-bytesLeft],
+                  MIN(maxSend, bytesLeft), 0);
+
+        if (SocketTraceIsActive) {
+            if (rc < 0)
+                fprintf(stderr, "Abyss socket: send() failed.  errno=%d (%s)",
+                        errno, strerror(errno));
+            else if (rc == 0)
+                fprintf(stderr, "Abyss socket: send() failed.  "
+                        "Socket closed.\n");
+            else
+                fprintf(stderr, "Abyss socket: sent %u bytes: '%.*s'\n",
+                        rc, rc, &buffer[len-bytesLeft]);
+        }
+        if (rc <= 0)
+            /* 0 means connection closed; < 0 means severe error */
+            error = TRUE;
+        else
+            bytesLeft -= rc;
+    }
+    *failedP = error;
+}
+
+
+
+static uint32_t
+socketRead(TSocket * const socketP, 
+           char *    const buffer, 
+           uint32_t  const len) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    int rc;
+    rc = recv(socketUnixP->fd, buffer, len, 0);
+    if (SocketTraceIsActive) {
+        if (rc < 0)
+            fprintf(stderr, "Abyss socket: recv() failed.  errno=%d (%s)",
+                    errno, strerror(errno));
+        else 
+            fprintf(stderr, "Abyss socket: read %u bytes: '%.*s'\n",
+                    len, (int)len, buffer);
+    }
+    return rc;
+}
+
+
+
+abyss_bool
+socketConnect(TSocket * const socketP,
+              TIPAddr * const addrP,
+              uint16_t  const portNumber) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    struct sockaddr_in name;
+    int rc;
+
+    name.sin_family = AF_INET;
+    name.sin_port = htons(portNumber);
+    name.sin_addr = *addrP;
+
+    rc = connect(socketUnixP->fd, (struct sockaddr *)&name, sizeof(name));
+
+    return rc != -1;
+}
+
+
+
+abyss_bool
+socketBind(TSocket * const socketP,
+           TIPAddr * const addrP,
+           uint16_t  const portNumber) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    struct sockaddr_in name;
+    int rc;
+
+    name.sin_family = AF_INET;
+    name.sin_port   = htons(portNumber);
+    if (addrP)
+        name.sin_addr = *addrP;
+    else
+        name.sin_addr.s_addr = INADDR_ANY;
+
+    rc = bind(socketUnixP->fd, (struct sockaddr *)&name, sizeof(name));
+
+    return (rc != -1);
+}
+
+
+
+abyss_bool
+socketListen(TSocket * const socketP,
+             uint32_t  const backlog) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    int32_t const minus1 = -1;
+
+    int rc;
+
+    /* Disable the Nagle algorithm to make persistant connections faster */
+
+    setsockopt(socketUnixP->fd, IPPROTO_TCP,TCP_NODELAY,
+               &minus1, sizeof(minus1));
+
+    rc = listen(socketUnixP->fd, backlog);
+
+    return (rc != -1);
+}
+
+
+
+static void
+socketAccept(TSocket *    const listenSocketP,
+             abyss_bool * const connectedP,
+             abyss_bool * const failedP,
+             TSocket **   const acceptedSocketPP,
+             TIPAddr *    const ipAddrP) {
+/*----------------------------------------------------------------------------
+   Accept a connection on the listening socket 'listenSocketP'.  Return as
+   *acceptedSocketPP the socket for the accepted connection.
+
+   If no connection is waiting on 'listenSocketP', wait until one is.
+
+   If we receive a signal while waiting, return immediately.
+
+   Return *connectedP true iff we accepted a connection.  Return
+   *failedP true iff we were unable to accept a connection for some
+   reason other than that we were interrupted.  Return both false if
+   our wait for a connection was interrupted by a signal.
+-----------------------------------------------------------------------------*/
+    struct socketUnix * const listenSocketUnixP = listenSocketP->implP;
+
+    abyss_bool connected, failed, interrupted;
+
+    connected  = FALSE;
+    failed      = FALSE;
+    interrupted = FALSE;
+
+    while (!connected && !failed && !interrupted) {
+        struct sockaddr_in sa;
+        socklen_t size = sizeof(sa);
+        int rc;
+        rc = accept(listenSocketUnixP->fd, (struct sockaddr *)&sa, &size);
+        if (rc >= 0) {
+            int const acceptedFd = rc;
+            struct socketUnix * acceptedSocketUnixP;
+
+            MALLOCVAR(acceptedSocketUnixP);
+
+            if (acceptedSocketUnixP) {
+                acceptedSocketUnixP->fd = acceptedFd;
+                acceptedSocketUnixP->userSuppliedFd = FALSE;
+                
+                SocketCreate(&vtbl, acceptedSocketUnixP, acceptedSocketPP);
+                if (!*acceptedSocketPP)
+                    failed = TRUE;
+                else {
+                    connected = TRUE;
+                    *ipAddrP = sa.sin_addr;
+                }
+                if (failed)
+                    free(acceptedSocketUnixP);
+            } else
+                failed = TRUE;
+            if (failed)
+                close(acceptedFd);
+        } else if (errno == EINTR)
+            interrupted = TRUE;
+        else
+            failed = TRUE;
+    }   
+    *failedP    = failed;
+    *connectedP = connected;
+}
+
+
+
+static uint32_t
+socketWait(TSocket *  const socketP,
+           abyss_bool const rd,
+           abyss_bool const wr,
+           uint32_t   const timems) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    fd_set rfds, wfds;
+    struct timeval tv;
+
+    if (SocketTraceIsActive)
+        fprintf(stderr, "Waiting %u milliseconds for %s %s of socket\n",
+                timems, rd ? "READ" : "", wr ? "WRITE" : "");
+
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+
+    if (rd)
+        FD_SET(socketUnixP->fd, &rfds);
+
+    if (wr)
+        FD_SET(socketUnixP->fd, &wfds);
+
+    tv.tv_sec  = timems / 1000;
+    tv.tv_usec = timems % 1000;
+
+    for (;;) {
+        int rc;
+
+        rc = select(socketUnixP->fd + 1, &rfds, &wfds, NULL,
+                    (timems == TIME_INFINITE ? NULL : &tv));
+
+        switch(rc) {   
+        case 0: /* time out */
+            return 0;
+
+        case -1:  /* socket error */
+            if (errno == EINTR)
+                break;
+            
+            return 0;
+            
+        default:
+            if (FD_ISSET(socketUnixP->fd, &rfds))
+                return 1;
+            if (FD_ISSET(socketUnixP->fd, &wfds))
+                return 2;
+            return 0;
+        }
+    }
+}
+
+
+
+static uint32_t
+socketAvailableReadBytes(TSocket * const socketP) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    uint32_t x;
+    int rc;
+
+    rc = ioctl(socketUnixP->fd, FIONREAD, &x);
+
+    if (SocketTraceIsActive) {
+        if (rc == 0)
+            fprintf(stderr, "Socket has %u bytes available\n", x);
+        else
+            fprintf(stderr, "ioctl(FIONREAD) failed, errno=%d (%s)\n",
+                    errno, strerror(errno));
+    }
+    return rc == 0 ? x : 0;
+}
+
+
+
+static void
+socketGetPeerName(TSocket *    const socketP,
+                  TIPAddr *    const ipAddrP,
+                  uint16_t *   const portNumberP,
+                  abyss_bool * const successP) {
+
+    struct socketUnix * const socketUnixP = socketP->implP;
+
+    socklen_t addrlen;
+    int rc;
+    struct sockaddr sockAddr;
+
+    addrlen = sizeof(sockAddr);
+    
+    rc = getpeername(socketUnixP->fd, &sockAddr, &addrlen);
+
+    if (rc < 0) {
+        TraceMsg("getpeername() failed.  errno=%d (%s)",
+                 errno, strerror(errno));
+        *successP = FALSE;
+    } else {
+        if (addrlen != sizeof(sockAddr)) {
+            TraceMsg("getpeername() returned a socket address of the wrong "
+                     "size: %u.  Expected %u", addrlen, sizeof(sockAddr));
+            *successP = FALSE;
+        } else {
+            if (sockAddr.sa_family != AF_INET) {
+                TraceMsg("Socket does not use the Inet (IP) address "
+                         "family.  Instead it uses family %d",
+                         sockAddr.sa_family);
+                *successP = FALSE;
+            } else {
+                struct sockaddr_in * const sockAddrInP = (struct sockaddr_in *)
+                    &sockAddr;
+
+                *ipAddrP     = sockAddrInP->sin_addr;
+                *portNumberP = sockAddrInP->sin_port;
+
+                *successP = TRUE;
+            }
+        }
+    }
+}
+
+
+
+static uint32_t
+socketError(TSocket * const socketP) {
+
+    if (socketP){} /* defeat compiler warning */
+
+    return errno;
+}
diff --git a/lib/abyss/src/socket_unix.h b/lib/abyss/src/socket_unix.h
new file mode 100644 (file)
index 0000000..845a4fc
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef SOCKET_UNIX_H_INCLUDED
+#define SOCKET_UNIX_H_INCLUDED
+
+void
+SocketUnixInit(abyss_bool * const succeededP);
+
+void
+SocketUnixTerm(void);
+
+#endif
diff --git a/lib/abyss/src/socket_win.c b/lib/abyss/src/socket_win.c
new file mode 100644 (file)
index 0000000..058c322
--- /dev/null
@@ -0,0 +1,456 @@
+/*=============================================================================\r
+                                 socket_win.c\r
+===============================================================================\r
+  This is the implementation of TSocket for a Windows Winsock socket.\r
+=============================================================================*/\r
+\r
+#include "xmlrpc_config.h"\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+#include <winsock.h>\r
+\r
+#include "xmlrpc-c/util_int.h"\r
+#include "mallocvar.h"\r
+#include "trace.h"\r
+\r
+#include "socket.h"\r
+\r
+\r
+struct socketWin {\r
+/*----------------------------------------------------------------------------\r
+   The properties/state of a TSocket unique to a Unix TSocket.\r
+-----------------------------------------------------------------------------*/\r
+    SOCKET fd;\r
+    abyss_bool userSuppliedWinsock;\r
+        /* 'socket' was supplied by the user; it belongs to him */\r
+};\r
+\r
+\r
+\r
+void\r
+SocketWinInit(abyss_bool * const succeededP) {\r
+\r
+    WORD wVersionRequested;\r
+    WSADATA wsaData;\r
+    int err;\r
+\r
+    wVersionRequested = MAKEWORD(2, 0);\r
+\r
+    err = WSAStartup(wVersionRequested, &wsaData);\r
+    *succeededP = (err == 0);\r
+}\r
+\r
+\r
+\r
+void\r
+SocketWinTerm(void) {\r
+\r
+    WSACleanup();\r
+}\r
+\r
+\r
+\r
+static SocketDestroyImpl            socketDestroy;\r
+static SocketWriteImpl              socketWrite;\r
+static SocketReadImpl               socketRead;\r
+static SocketConnectImpl            socketConnect;\r
+static SocketBindImpl               socketBind;\r
+static SocketListenImpl             socketListen;\r
+static SocketAcceptImpl             socketAccept;\r
+static SocketErrorImpl              socketError;\r
+static SocketWaitImpl               socketWait;\r
+static SocketAvailableReadBytesImpl socketAvailableReadBytes;\r
+static SocketGetPeerNameImpl        socketGetPeerName;\r
+\r
+\r
+static struct TSocketVtbl const vtbl = {\r
+    &socketDestroy,\r
+    &socketWrite,\r
+    &socketRead,\r
+    &socketConnect,\r
+    &socketBind,\r
+    &socketListen,\r
+    &socketAccept,\r
+    &socketError,\r
+    &socketWait,\r
+    &socketAvailableReadBytes,\r
+    &socketGetPeerName\r
+};\r
+\r
+\r
+\r
+void\r
+SocketWinCreate(TSocket ** const socketPP) {\r
+\r
+    struct socketWin * socketWinP;\r
+\r
+    MALLOCVAR(socketWinP);\r
+\r
+    if (socketWinP) {\r
+        SOCKET rc;\r
+        rc = socket(AF_INET, SOCK_STREAM, 0);\r
+        if (rc < 0)\r
+            *socketPP = NULL;\r
+        else {\r
+            socketWinP->fd = rc;\r
+            socketWinP->userSuppliedWinsock = FALSE;\r
+\r
+            {\r
+                int32_t n = 1;\r
+                int rc;\r
+                rc = setsockopt(socketWinP->fd, SOL_SOCKET, SO_REUSEADDR,\r
+                                (char*)&n, sizeof(n));\r
+                if (rc < 0)\r
+                    *socketPP = NULL;\r
+                else\r
+                    SocketCreate(&vtbl, socketWinP, socketPP);\r
+            }\r
+            if (!*socketPP)\r
+                closesocket(socketWinP->fd);\r
+        }\r
+        if (!*socketPP)\r
+            free(socketWinP);\r
+    } else\r
+        *socketPP = NULL;\r
+}\r
+\r
+\r
+\r
+void\r
+SocketWinCreateWinsock(SOCKET     const winsock,\r
+                       TSocket ** const socketPP) {\r
+\r
+    struct socketWin * socketWinP;\r
+\r
+    MALLOCVAR(socketWinP);\r
+\r
+    if (socketWinP) {\r
+        socketWinP->fd = winsock;\r
+        socketWinP->userSuppliedWinsock = TRUE;\r
+\r
+        SocketCreate(&vtbl, socketWinP, socketPP);\r
+\r
+        if (!*socketPP)\r
+            free(socketWinP);\r
+    } else\r
+        *socketPP = NULL;\r
+}\r
+\r
+\r
+\r
+void\r
+socketDestroy(TSocket * const socketP) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    if (!socketWinP->userSuppliedWinsock)\r
+        closesocket(socketWinP->fd);\r
+\r
+    free(socketWinP);\r
+}\r
+\r
+\r
+\r
+void\r
+socketWrite(TSocket *             const socketP,\r
+            const unsigned char * const buffer,\r
+            uint32_t              const len,\r
+            abyss_bool *          const failedP) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    size_t bytesLeft;\r
+    abyss_bool error;\r
+\r
+    assert(sizeof(size_t) >= sizeof(len));\r
+\r
+    for (bytesLeft = len, error = FALSE;\r
+         bytesLeft > 0 && !error;\r
+        ) {\r
+        size_t const maxSend = (size_t)(-1) >> 1;\r
+\r
+        int rc;\r
+\r
+        rc = send(socketWinP->fd, &buffer[len-bytesLeft],\r
+                  MIN(maxSend, bytesLeft), 0);\r
+\r
+        if (rc <= 0)\r
+            /* 0 means connection closed; < 0 means severe error */\r
+            error = TRUE;\r
+        else\r
+            bytesLeft -= rc;\r
+    }\r
+    *failedP = error;\r
+}\r
+\r
+\r
+\r
+uint32_t\r
+socketRead(TSocket * const socketP,\r
+           char *    const buffer,\r
+           uint32_t  const len) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    int rc;\r
+    rc = recv(socketWinP->fd, buffer, len, 0);\r
+    return rc;\r
+}\r
+\r
+\r
+\r
+abyss_bool\r
+socketConnect(TSocket * const socketP,\r
+              TIPAddr * const addrP,\r
+              uint16_t  const portNumber) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    struct sockaddr_in name;\r
+    int rc;\r
+\r
+    name.sin_family = AF_INET;\r
+    name.sin_port = htons(portNumber);\r
+    name.sin_addr = *addrP;\r
+\r
+    rc = connect(socketWinP->fd, (struct sockaddr *)&name, sizeof(name));\r
+\r
+    return rc != -1;\r
+}\r
+\r
+\r
+\r
+abyss_bool\r
+socketBind(TSocket * const socketP,\r
+           TIPAddr * const addrP,\r
+           uint16_t  const portNumber) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    struct sockaddr_in name;\r
+    int rc;\r
+\r
+    name.sin_family = AF_INET;\r
+    name.sin_port   = htons(portNumber);\r
+    if (addrP)\r
+        name.sin_addr = *addrP;\r
+    else\r
+        name.sin_addr.s_addr = INADDR_ANY;\r
+\r
+    rc = bind(socketWinP->fd, (struct sockaddr *)&name, sizeof(name));\r
+\r
+    return (rc != -1);\r
+}\r
+\r
+\r
+\r
+abyss_bool\r
+socketListen(TSocket * const socketP,\r
+             uint32_t  const backlog) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    int32_t const minus1 = -1;\r
+\r
+    int rc;\r
+\r
+    /* Disable the Nagle algorithm to make persistant connections faster */\r
+\r
+    setsockopt(socketWinP->fd, IPPROTO_TCP,TCP_NODELAY,\r
+               (const char *)&minus1, sizeof(minus1));\r
+\r
+    rc = listen(socketWinP->fd, backlog);\r
+\r
+    return (rc != -1);\r
+}\r
+\r
+\r
+\r
+static void\r
+socketAccept(TSocket *    const listenSocketP,\r
+             abyss_bool * const connectedP,\r
+             abyss_bool * const failedP,\r
+             TSocket **   const acceptedSocketPP,\r
+             TIPAddr *    const ipAddrP) {\r
+/*----------------------------------------------------------------------------\r
+   Accept a connection on the listening socket 'listenSocketP'.  Return as\r
+   *acceptedSocketPP the socket for the accepted connection.\r
+\r
+   If no connection is waiting on 'listenSocketP', wait until one is.\r
+\r
+   If we receive a signal while waiting, return immediately.\r
+\r
+   Return *connectedP true iff we accepted a connection.  Return\r
+   *failedP true iff we were unable to accept a connection for some\r
+   reason other than that we were interrupted.  Return both false if\r
+   our wait for a connection was interrupted by a signal.\r
+-----------------------------------------------------------------------------*/\r
+    struct socketWin * const listenSocketWinP = listenSocketP->implP;\r
+\r
+    abyss_bool connected, failed, interrupted;\r
+\r
+    connected   = FALSE;\r
+    failed      = FALSE;\r
+    interrupted = FALSE;\r
+\r
+    while (!connected && !failed && !interrupted) {\r
+        struct sockaddr_in sa;\r
+        socklen_t size = sizeof(sa);\r
+        int rc;\r
+        rc = accept(listenSocketWinP->fd, (struct sockaddr *)&sa, &size);\r
+        if (rc >= 0) {\r
+            SOCKET const acceptedWinsock = rc;\r
+            struct socketWin * acceptedSocketWinP;\r
+\r
+            MALLOCVAR(acceptedSocketWinP);\r
+\r
+            if (acceptedSocketWinP) {\r
+                acceptedSocketWinP->fd = acceptedWinsock;\r
+                acceptedSocketWinP->userSuppliedWinsock = FALSE;\r
+\r
+                SocketCreate(&vtbl, acceptedSocketWinP, acceptedSocketPP);\r
+                if (!*acceptedSocketPP)\r
+                    failed = TRUE;\r
+                else {\r
+                    connected = TRUE;\r
+                    *ipAddrP = sa.sin_addr;\r
+                }\r
+                if (failed)\r
+                    free(acceptedSocketWinP);\r
+            } else\r
+                failed = TRUE;\r
+            if (failed)\r
+                closesocket(acceptedWinsock);\r
+        } else if (socketError(NULL) == WSAEINTR)\r
+            interrupted = TRUE;\r
+        else\r
+            failed = TRUE;\r
+    }\r
+    *failedP    = failed;\r
+    *connectedP = connected;\r
+}\r
+\r
+\r
+\r
+static uint32_t\r
+socketWait(TSocket *  const socketP,\r
+           abyss_bool const rd,\r
+           abyss_bool const wr,\r
+           uint32_t   const timems) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    fd_set rfds, wfds;\r
+    TIMEVAL tv;\r
+\r
+    FD_ZERO(&rfds);\r
+    FD_ZERO(&wfds);\r
+\r
+    if (rd)\r
+        FD_SET(socketWinP->fd, &rfds);\r
+\r
+    if (wr)\r
+        FD_SET(socketWinP->fd, &wfds);\r
+\r
+    tv.tv_sec  = timems / 1000;\r
+    tv.tv_usec = timems % 1000;\r
+\r
+    for (;;) {\r
+        int rc;\r
+\r
+        rc = select(socketWinP->fd + 1, &rfds, &wfds, NULL,\r
+                    (timems == TIME_INFINITE ? NULL : &tv));\r
+\r
+        switch(rc) {\r
+        case 0: /* time out */\r
+            return 0;\r
+\r
+        case -1:  /* socket error */\r
+            if (socketError(NULL) == WSAEINTR)\r
+                break;\r
+\r
+            return 0;\r
+\r
+        default:\r
+            if (FD_ISSET(socketWinP->fd, &rfds))\r
+                return 1;\r
+            if (FD_ISSET(socketWinP->fd, &wfds))\r
+                return 2;\r
+            return 0;\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+static uint32_t\r
+socketAvailableReadBytes(TSocket * const socketP) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    uint32_t x;\r
+    int rc;\r
+\r
+    rc = ioctlsocket(socketWinP->fd, FIONREAD, &x);\r
+\r
+    return rc == 0 ? x : 0;\r
+}\r
+\r
+\r
+\r
+static void\r
+socketGetPeerName(TSocket *    const socketP,\r
+                  TIPAddr *    const ipAddrP,\r
+                  uint16_t *   const portNumberP,\r
+                  abyss_bool * const successP) {\r
+\r
+    struct socketWin * const socketWinP = socketP->implP;\r
+\r
+    socklen_t addrlen;\r
+    int rc;\r
+    struct sockaddr sockAddr;\r
+\r
+    addrlen = sizeof(sockAddr);\r
+\r
+    rc = getpeername(socketWinP->fd, &sockAddr, &addrlen);\r
+\r
+    if (rc < 0) {\r
+        TraceMsg("getpeername() failed.  errno=%d (%s)",\r
+                 errno, strerror(errno));\r
+        *successP = FALSE;\r
+    } else {\r
+        if (addrlen != sizeof(sockAddr)) {\r
+            TraceMsg("getpeername() returned a socket address of the wrong "\r
+                     "size: %u.  Expected %u", addrlen, sizeof(sockAddr));\r
+            *successP = FALSE;\r
+        } else {\r
+            if (sockAddr.sa_family != AF_INET) {\r
+                TraceMsg("Socket does not use the Inet (IP) address "\r
+                         "family.  Instead it uses family %d",\r
+                         sockAddr.sa_family);\r
+                *successP = FALSE;\r
+            } else {\r
+                struct sockaddr_in * const sockAddrInP = (struct sockaddr_in *)\r
+                    &sockAddr;\r
+\r
+                *ipAddrP     = sockAddrInP->sin_addr;\r
+                *portNumberP = sockAddrInP->sin_port;\r
+\r
+                *successP = TRUE;\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+static uint32_t\r
+socketError(TSocket * const socketP) {\r
+    return (uint32_t)WSAGetLastError();\r
+}\r
+\r
+\r
+\r
diff --git a/lib/abyss/src/socket_win.h b/lib/abyss/src/socket_win.h
new file mode 100644 (file)
index 0000000..f64f48d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef SOCKET_WIN_H_INCLUDED\r
+#define SOCKET_WIN_H_INCLUDED\r
+\r
+void\r
+SocketWinInit(abyss_bool * const succeededP);\r
+\r
+void\r
+SocketWinTerm(void);\r
+\r
+#endif\r
diff --git a/lib/abyss/src/thread.h b/lib/abyss/src/thread.h
new file mode 100644 (file)
index 0000000..dfef056
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef THREAD_H_INCLUDED
+#define THREAD_H_INCLUDED
+
+/*********************************************************************
+** Thread
+*********************************************************************/
+
+typedef struct abyss_thread TThread;
+
+void
+ThreadPoolInit(void);
+
+typedef void TThreadProc(void * const userHandleP);
+typedef void TThreadDoneFn(void * const userHandleP);
+
+void
+ThreadCreate(TThread **      const threadPP,
+             void *          const userHandle,
+             TThreadProc   * const func,
+             TThreadDoneFn * const threadDone,
+             abyss_bool      const useSigchld,
+             const char **   const errorP);
+
+abyss_bool
+ThreadRun(TThread * const threadP);
+
+abyss_bool
+ThreadStop(TThread * const threadP);
+
+abyss_bool
+ThreadKill(TThread * threadP);
+
+void
+ThreadWaitAndRelease(TThread * const threadP);
+
+void
+ThreadExit(int const retValue);
+
+void
+ThreadRelease(TThread * const threadP);
+
+abyss_bool
+ThreadForks(void);
+
+void
+ThreadUpdateStatus(TThread * const threadP);
+
+#ifndef WIN32
+void
+ThreadHandleSigchld(pid_t const pid);
+#endif
+
+/*********************************************************************
+** Mutex
+*********************************************************************/
+
+#ifdef WIN32
+typedef HANDLE TMutex;
+#else
+#include <pthread.h>
+typedef pthread_mutex_t TMutex;
+#endif  /* WIN32 */
+
+abyss_bool MutexCreate(TMutex *m);
+abyss_bool MutexLock(TMutex *m);
+abyss_bool MutexUnlock(TMutex *m);
+abyss_bool MutexTryLock(TMutex *m);
+void MutexFree(TMutex *m);
+
+#endif
diff --git a/lib/abyss/src/thread_fork.c b/lib/abyss/src/thread_fork.c
new file mode 100644 (file)
index 0000000..b1727c7
--- /dev/null
@@ -0,0 +1,323 @@
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <wait.h>
+#include <signal.h>
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "mallocvar.h"
+#include "thread.h"
+
+
+static void
+blockSignalClass(int        const signalClass,
+                 sigset_t * const oldBlockedSetP) {
+
+    sigset_t newBlockedSet;
+
+    sigemptyset(&newBlockedSet);
+    sigaddset(&newBlockedSet, signalClass);
+
+    sigprocmask(SIG_BLOCK, &newBlockedSet, oldBlockedSetP);
+}
+
+
+
+struct abyss_thread {
+    struct abyss_thread * nextInPoolP;
+    TThreadDoneFn * threadDone;
+    void * userHandle;
+    pid_t pid;
+    abyss_bool useSigchld;
+        /* This means that user is going to call ThreadHandleSigchld()
+           when it gets a death of a child signal for this process.  If
+           false, he's going to leave us in the dark, so we'll have to
+           poll to know if the process is dead or not.
+        */
+};
+
+
+/* Because signals are global, we need this global variable in order for
+   the signal handler to figure out to what thread the signal belongs.
+*/
+
+/* We use a singly linked list.  Every time we access it, we have to run
+   the whole chain.  To make this scale up, we should replace it with
+   a doubly linked list and some kind of index by PID.
+
+   But large scale systems probably aren't using fork threads anyway.
+*/
+
+static struct {
+    struct abyss_thread * firstP;
+} ThreadPool;
+   
+
+
+void
+ThreadPoolInit(void) {
+
+    ThreadPool.firstP = NULL;
+}
+
+
+
+static struct abyss_thread *
+findThread(pid_t const pid) {
+
+    struct abyss_thread * p;
+
+    for (p = ThreadPool.firstP; p && p->pid != pid; p = p->nextInPoolP);
+    
+    return p;
+}
+
+
+
+static void
+addToPool(struct abyss_thread * const threadP) {
+
+    if (ThreadPool.firstP == NULL)
+        ThreadPool.firstP = threadP;
+    else {
+        struct abyss_thread * p;
+
+        for (p = ThreadPool.firstP; p->nextInPoolP; p = p->nextInPoolP);
+
+        /* p points to the last thread in the list */
+
+        p->nextInPoolP = threadP;
+    }
+}
+
+
+
+static void
+removeFromPool(struct abyss_thread * const threadP) {
+
+    if (threadP == ThreadPool.firstP)
+        ThreadPool.firstP = threadP->nextInPoolP;
+    else {
+        struct abyss_thread * p;
+
+        for (p = ThreadPool.firstP;
+             p && p->nextInPoolP != threadP;
+             p = p->nextInPoolP);
+        
+        if (p)
+            /* p points to thread right before the one we want to remove */
+            p->nextInPoolP = threadP->nextInPoolP;
+    }
+}
+
+
+
+void
+ThreadHandleSigchld(pid_t const pid) {
+/*----------------------------------------------------------------------------
+   Handle a death of a child signal for process 'pid', which may be one
+   of our threads.
+-----------------------------------------------------------------------------*/
+    struct abyss_thread * const threadP = findThread(pid);
+
+    if (threadP) {
+        if (threadP->threadDone)
+            threadP->threadDone(threadP->userHandle);
+        threadP->pid = 0;
+    }
+    /* Note that threadDone might free *threadP */
+}
+
+
+
+void
+ThreadUpdateStatus(TThread * const threadP) {
+
+    if (!threadP->useSigchld) {
+        if (threadP->pid) {
+            if (kill(threadP->pid, 0) != 0) {
+                if (threadP->threadDone)
+                    threadP->threadDone(threadP->userHandle);
+                threadP->pid = 0;
+            }
+        }
+    }
+}
+
+
+
+void
+ThreadCreate(TThread **      const threadPP,
+             void *          const userHandle,
+             TThreadProc   * const func,
+             TThreadDoneFn * const threadDone,
+             abyss_bool      const useSigchld,
+             const char **   const errorP) {
+    
+    TThread * threadP;
+
+    MALLOCVAR(threadP);
+    if (threadP == NULL)
+        xmlrpc_asprintf(errorP,
+                        "Can't allocate memory for thread descriptor.");
+    else {
+        sigset_t oldBlockedSet;
+        pid_t rc;
+
+        threadP->nextInPoolP = NULL;
+        threadP->threadDone  = threadDone;
+        threadP->userHandle  = userHandle;
+        threadP->useSigchld  = useSigchld;
+        threadP->pid         = 0;
+
+        /* We have to be sure we don't get the SIGCHLD for this child's
+           death until the child is properly registered in the thread pool
+           so that the handler will know who he is.
+        */
+        blockSignalClass(SIGCHLD, &oldBlockedSet);
+
+        rc = fork();
+        
+        if (rc < 0)
+            xmlrpc_asprintf(errorP, "fork() failed, errno=%d (%s)",
+                            errno, strerror(errno));
+        else if (rc == 0) {
+            /* This is the child */
+            (*func)(userHandle);
+            exit(0);
+        } else {
+            /* This is the parent */
+            threadP->pid = rc;
+
+            addToPool(threadP);
+
+            sigprocmask(SIG_SETMASK, &oldBlockedSet, NULL);  /* restore */
+
+            *errorP = NULL;
+            *threadPP = threadP;
+        }
+        if (*errorP) {
+            removeFromPool(threadP);
+            free(threadP);
+        }
+    }
+}
+
+
+
+abyss_bool
+ThreadRun(TThread * const threadP ATTR_UNUSED) {
+    return TRUE;    
+}
+
+
+
+abyss_bool
+ThreadStop(TThread * const threadP ATTR_UNUSED) {
+    return TRUE;
+}
+
+
+
+abyss_bool
+ThreadKill(TThread * const threadP ATTR_UNUSED) {
+    return TRUE;
+}
+
+
+
+void
+ThreadWaitAndRelease(TThread * const threadP) {
+
+    if (threadP->pid) {
+        int exitStatus;
+
+        waitpid(threadP->pid, &exitStatus, 0);
+
+        threadP->threadDone(threadP->userHandle);
+
+        threadP->pid = 0;
+    }
+    ThreadRelease(threadP);
+}
+
+
+
+void
+ThreadExit(int const retValue) {
+
+    /* Note that the OS will automatically send a SIGCHLD signal to
+       the parent process after we exit.  The handler for that signal
+       will run threadDone in parent's context.  Alternatively, if
+       the parent is set up for signals, the parent will eventually
+       poll for the existence of our PID and call threadDone when he
+       sees we've gone.
+    */
+
+    exit(retValue);
+}
+
+
+
+void
+ThreadRelease(TThread * const threadP) {
+
+    removeFromPool(threadP);
+    free(threadP);
+}
+
+
+
+abyss_bool
+ThreadForks(void) {
+
+    return TRUE;
+}
+
+
+
+/*********************************************************************
+** Mutex
+*********************************************************************/
+
+/* As two processes don't share memory, there is nothing to synchronize,
+   so locking is a no-op.
+*/
+
+abyss_bool
+MutexCreate(TMutex * const mutexP ATTR_UNUSED) {
+    return TRUE;
+}
+
+
+
+abyss_bool
+MutexLock(TMutex * const mutexP ATTR_UNUSED) {
+    return TRUE;
+}
+
+
+
+abyss_bool
+MutexUnlock(TMutex * const mutexP ATTR_UNUSED) {
+    return TRUE;
+}
+
+
+
+abyss_bool
+MutexTryLock(TMutex * const mutexP ATTR_UNUSED) {
+    return TRUE;
+}
+
+
+
+void
+MutexFree(TMutex * const mutexP ATTR_UNUSED) {
+
+}
diff --git a/lib/abyss/src/thread_pthread.c b/lib/abyss/src/thread_pthread.c
new file mode 100644 (file)
index 0000000..69c62b1
--- /dev/null
@@ -0,0 +1,221 @@
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "xmlrpc_config.h"
+
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+
+#include "xmlrpc-c/abyss.h"
+
+#include "thread.h"
+
+
+
+struct abyss_thread {
+    pthread_t       thread;
+    void *          userHandle;
+    TThreadProc *   func;
+    TThreadDoneFn * threadDone;
+};
+
+/* We used to have THREAD_STACK_SIZE = 16K, which was said to be the
+   minimum stack size on Win32.  Scott Kolodzeski found in November
+   2005 that this was insufficient for 64 bit Solaris -- we fail
+   when creating the first thread.  So we changed to 128K.
+*/
+#define  THREAD_STACK_SIZE (128*1024L)
+
+
+typedef void * (pthreadStartRoutine)(void *);
+
+
+
+static pthreadStartRoutine pthreadStart;
+
+static void *
+pthreadStart(void * const arg) {
+
+    struct abyss_thread * const threadP = arg;
+    abyss_bool const executeTrue = true;
+
+    pthread_cleanup_push(threadP->threadDone, threadP->userHandle);
+
+    threadP->func(threadP->userHandle);
+
+    pthread_cleanup_pop(executeTrue);
+
+    return NULL;
+}
+
+
+
+void
+ThreadCreate(TThread **      const threadPP,
+             void *          const userHandle,
+             TThreadProc   * const func,
+             TThreadDoneFn * const threadDone,
+             abyss_bool      const useSigchld ATTR_UNUSED,
+             const char **   const errorP) {
+
+    TThread * threadP;
+
+    MALLOCVAR(threadP);
+    if (threadP == NULL)
+        xmlrpc_asprintf(errorP,
+                        "Can't allocate memory for thread descriptor.");
+    else {
+        pthread_attr_t attr;
+        int rc;
+
+        pthread_attr_init(&attr);
+
+        pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
+        
+        threadP->userHandle = userHandle;
+        threadP->func       = func;
+        threadP->threadDone = threadDone;
+
+        rc = pthread_create(&threadP->thread, &attr,
+                            pthreadStart, threadP);
+        if (rc == 0) {
+            *errorP = NULL;
+            *threadPP = threadP;
+        } else
+            xmlrpc_asprintf(
+                errorP, "pthread_create() failed, errno = %d (%s)",
+                errno, strerror(errno));
+        
+        pthread_attr_destroy(&attr);
+
+        if (*errorP)
+            free(threadP);
+    }
+}
+
+
+
+abyss_bool
+ThreadRun(TThread * const threadP ATTR_UNUSED) {
+    return TRUE;    
+}
+
+
+
+abyss_bool
+ThreadStop(TThread * const threadP ATTR_UNUSED) {
+    return TRUE;
+}
+
+
+
+abyss_bool
+ThreadKill(TThread * const threadP ATTR_UNUSED) {
+
+    return (pthread_kill(threadP->thread, SIGTERM) == 0);
+}
+
+
+
+void
+ThreadWaitAndRelease(TThread * const threadP) {
+
+    void * threadReturn;
+
+    pthread_join(threadP->thread, &threadReturn);
+
+    free(threadP);
+}
+
+
+
+void
+ThreadExit(int const retValue) {
+
+    pthread_exit((void*)&retValue);
+
+    /* Note that the above runs our cleanup routine (which we registered
+       with pthread_cleanup_push() before exiting.
+    */
+}
+
+
+
+void
+ThreadRelease(TThread * const threadP) {
+
+    pthread_detach(threadP->thread);
+
+    free(threadP);
+}
+
+
+
+abyss_bool
+ThreadForks(void) {
+
+    return FALSE;
+}
+
+
+
+void
+ThreadUpdateStatus(TThread * const threadP ATTR_UNUSED) {
+
+    /* Threads keep their own statuses up to date, so there's nothing
+       to do here.
+    */
+}
+
+
+
+void
+ThreadHandleSigchld(pid_t const pid ATTR_UNUSED) {
+
+    /* Death of a child signals have nothing to do with pthreads */
+}
+
+
+
+/*********************************************************************
+** Mutex
+*********************************************************************/
+
+
+
+abyss_bool
+MutexCreate(TMutex * const mutexP) {
+
+    return (pthread_mutex_init(mutexP, NULL) == 0);
+}
+
+
+
+abyss_bool
+MutexLock(TMutex * const mutexP) {
+    return (pthread_mutex_lock(mutexP) == 0);
+}
+
+
+
+abyss_bool
+MutexUnlock(TMutex * const mutexP) {
+    return (pthread_mutex_unlock(mutexP) == 0);
+}
+
+
+
+abyss_bool
+MutexTryLock(TMutex * const mutexP) {
+    return (pthread_mutex_trylock(mutexP) == 0);
+}
+
+
+
+void
+MutexFree(TMutex * const mutexP) {
+    pthread_mutex_destroy(mutexP);
+}
diff --git a/lib/abyss/src/thread_windows.c b/lib/abyss/src/thread_windows.c
new file mode 100644 (file)
index 0000000..4a6868a
--- /dev/null
@@ -0,0 +1,167 @@
+#include <process.h>
+#include <windows.h>
+
+#include "xmlrpc_config.h"
+
+#include "mallocvar.h"
+#include "xmlrpc-c/string_int.h"
+
+#include "xmlrpc-c/abyss.h"
+
+#include "thread.h"
+
+
+
+struct abyss_thread {
+    HANDLE          handle;
+    void *          userHandle;
+    TThreadDoneFn * threadDone;
+};
+
+#define  THREAD_STACK_SIZE (16*1024L)
+
+
+typedef uint32_t (WINAPI WinThreadProc)(void *);
+
+
+void
+ThreadCreate(TThread **      const threadPP,
+             void *          const userHandle,
+             TThreadProc   * const func,
+             TThreadDoneFn * const threadDone,
+             abyss_bool      const useSigchld,
+             const char **   const errorP) {
+
+    DWORD z;
+    TThread * threadP;
+
+    MALLOCVAR(threadP);
+
+    if (threadP == NULL)
+        xmlrpc_asprintf(errorP,
+                        "Can't allocate memory for thread descriptor.");
+    else {
+        threadP->userHandle = userHandle;
+        threadP->threadDone = threadDone;
+        threadP->handle = (HANDLE)_beginthreadex(NULL, THREAD_STACK_SIZE, func,
+                                         userHandle,
+                                         CREATE_SUSPENDED, &z);
+        if (threadP->handle == NULL)
+            xmlrpc_asprintf(errorP, "_beginthreadex() failed.");
+        else {
+            *errorP = NULL;
+            *threadPP = threadP;
+        }
+        if (*errorP)
+            free(threadP);
+    }
+}
+
+
+
+abyss_bool
+ThreadRun(TThread * const threadP) {
+    return (ResumeThread(threadP->handle) != 0xFFFFFFFF);
+}
+
+
+
+abyss_bool
+ThreadStop(TThread * const threadP) {
+
+    return (SuspendThread(threadP->handle) != 0xFFFFFFFF);
+}
+
+
+
+abyss_bool
+ThreadKill(TThread * const threadP) {
+    return (TerminateThread(threadP->handle, 0) != 0);
+}
+
+
+
+void
+ThreadWaitAndRelease(TThread * const threadP) {
+
+    ThreadRelease(threadP);
+
+    if (threadP->threadDone)
+        threadP->threadDone(threadP->userHandle);
+
+    free(threadP);
+}
+
+
+
+void
+ThreadExit(int const retValue) {
+
+    _endthreadex(retValue);
+}
+
+
+
+void
+ThreadRelease(TThread * const threadP) {
+
+    CloseHandle(threadP->handle);
+}
+
+
+
+abyss_bool
+ThreadForks(void) {
+
+    return FALSE;
+}
+
+
+
+void
+ThreadUpdateStatus(TThread * const threadP ATTR_UNUSED) {
+
+    /* Threads keep their own statuses up to date, so there's nothing
+       to do here.
+    */
+}
+
+
+
+abyss_bool
+MutexCreate(TMutex * const mutexP) {
+
+    *mutexP = CreateMutex(NULL, FALSE, NULL);
+
+    return (*mutexP != NULL);
+}
+
+
+
+abyss_bool
+MutexLock(TMutex * const mutexP) {
+
+    return (WaitForSingleObject(*mutexP, INFINITE) != WAIT_TIMEOUT);
+}
+
+
+
+abyss_bool
+MutexUnlock(TMutex * const mutexP) {
+    return ReleaseMutex(*mutexP);
+}
+
+
+
+abyss_bool
+MutexTryLock(TMutex * const mutexP) {
+    return (WaitForSingleObject(*mutexP, 0) != WAIT_TIMEOUT);
+}
+
+
+
+void
+MutexFree(TMutex * const mutexP) {
+    CloseHandle(*mutexP);
+}
+
diff --git a/lib/abyss/src/token.c b/lib/abyss/src/token.c
new file mode 100644 (file)
index 0000000..8616b95
--- /dev/null
@@ -0,0 +1,54 @@
+#include "xmlrpc-c/abyss.h"
+
+#include "token.h"
+
+void
+NextToken(const char ** const pP) {
+
+    abyss_bool gotToken;
+
+    gotToken = FALSE;
+
+    while (!gotToken) {
+        switch (**pP) {
+        case '\t':
+        case ' ':
+            ++(*pP);
+            break;
+        default:
+            gotToken = TRUE;
+        };
+    }
+}
+
+
+
+char *
+GetToken(char ** const pP) {
+
+    char * p0;
+        
+    p0 = *pP;
+
+    while (1) {
+        switch (**pP) {
+        case '\t':
+        case ' ':
+        case CR:
+        case LF:
+        case '\0':
+            if (p0 == *pP)
+                return NULL;
+
+            if (**pP) {
+                **pP = '\0';
+                ++(*pP);
+            };
+            return p0;
+
+        default:
+            ++(*pP);
+        };
+    }
+}
+
diff --git a/lib/abyss/src/token.h b/lib/abyss/src/token.h
new file mode 100644 (file)
index 0000000..a8458e4
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef ABYSS_TOKEN_H_INCLUDED
+#define ABYSS_TOKEN_H_INCLUDED
+
+void
+NextToken(const char ** const pP);
+
+char *
+GetToken(char ** const pP);
+
+
+#endif
diff --git a/lib/abyss/src/trace.c b/lib/abyss/src/trace.c
new file mode 100644 (file)
index 0000000..8079388
--- /dev/null
@@ -0,0 +1,78 @@
+/******************************************************************************
+**
+** trace.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "trace.h"
+
+/*********************************************************************
+** Tracing functions
+*********************************************************************/
+
+static void
+TraceVMsg(const char * const fmt,
+          va_list            argptr) {
+
+    vprintf(fmt,argptr);
+
+    printf("\n");
+}
+
+
+
+void
+TraceMsg(const char * const fmt, ...) {
+
+    va_list argptr;
+
+    va_start(argptr,fmt);
+    TraceVMsg(fmt,argptr);
+    va_end(argptr);
+}
+
+
+
+void
+TraceExit(const char * const fmt, ...) {
+
+    va_list argptr;
+
+    va_start(argptr,fmt);
+    TraceVMsg(fmt,argptr);
+    va_end(argptr);
+
+    exit(1);
+}
diff --git a/lib/abyss/src/trace.h b/lib/abyss/src/trace.h
new file mode 100644 (file)
index 0000000..849c0b3
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef TRACE_H_INCLUDED
+#define TRACE_H_INCLUDED
+
+void
+TraceMsg(const char * const fmt, ...);
+
+void
+TraceExit(const char * const fmt, ...);
+
+#endif
+
diff --git a/lib/abyss/version.txt b/lib/abyss/version.txt
new file mode 100644 (file)
index 0000000..13874ba
--- /dev/null
@@ -0,0 +1 @@
+0.3 (03/23/2000)
\ No newline at end of file
diff --git a/lib/curl_transport/Makefile b/lib/curl_transport/Makefile
new file mode 100644 (file)
index 0000000..7e0d421
--- /dev/null
@@ -0,0 +1,51 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+BUILDDIR = ../..
+endif
+
+include $(SRCDIR)/Makefile.config
+
+CURL_INCLUDES := $(shell curl-config --cflags)
+# We expect that curl-config --cflags just gives us -I options, because
+# we need just the -I options for 'make dep'.  Plus, it's scary to think
+# of what any other compiler flag would do to our compile.
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+LDFLAGS = $(LADD)
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
+  $(CURL_INCLUDES)
+
+default: all
+
+.PHONY: all
+all: xmlrpc_curl_transport.lo
+
+.PHONY: clean
+clean: clean-common
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: tags
+tags: TAGS
+
+.PHONY: distdir
+distdir:
+
+.PHONY: install
+install:
+
+.PHONY: dep
+dep: dep-common
+
+include $(SRCDIR)/Makefile.common
+
+include Makefile.depend
+
+xmlrpc_curl_transport.lo:%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+# Need this dependency for those who don't use Makefile.depend.
+# Without it, version.h doesn't get created.
+xmlrpc_curl_transport.lo: version.h
\ No newline at end of file
diff --git a/lib/curl_transport/Makefile.depend b/lib/curl_transport/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/curl_transport/xmlrpc_curl_transport.c b/lib/curl_transport/xmlrpc_curl_transport.c
new file mode 100644 (file)
index 0000000..530fab5
--- /dev/null
@@ -0,0 +1,1864 @@
+/*=============================================================================
+                           xmlrpc_curl_transport
+===============================================================================
+   Curl-based client transport for Xmlrpc-c
+
+   By Bryan Henderson 04.12.10.
+
+   Contributed to the public domain by its author.
+=============================================================================*/
+
+/*----------------------------------------------------------------------------
+   Curl global variables:
+
+   Curl maintains some minor information in process-global variables.
+   One must call curl_global_init() to initialize them before calling
+   any other Curl library function.  This is not state information --
+   it is constants.  They just aren't the kind of constants that the
+   library loader knows how to set, so there has to be this explicit
+   call to set them up.  The matching function curl_global_cleanup()
+   returns resources these use (to wit, the constants live in
+   malloc'ed storage and curl_global_cleanup() frees the storage).
+
+   So our setup_global_const transport operation calls
+   curl_global_init() and our teardown_global_const calls
+   curl_global_cleanup().
+
+   The Curl library is supposed to maintain a reference count for the
+   global constants so that multiple modules using the library and
+   independently calling curl_global_init() and curl_global_cleanup()
+   are not a problem.  But today, it just keeps a flag "I have been
+   initialized" and the first call to curl_global_cleanup() destroys
+   the constants for everybody.  Therefore, the user of the Xmlrpc-c
+   Curl client XML transport must make sure not to call
+   teardownGlobalConstants until everything else in his program is
+   done using the Curl library.
+
+   Note that curl_global_init() is not threadsafe (with or without the
+   reference count), therefore our setup_global_const is not, and must
+   be called when no other thread in the process is running.
+   Typically, one calls it right at the beginning of the program.
+
+   There are actually two other classes of global variables in the
+   Curl library, which we are ignoring: debug options and custom
+   memory allocator function identities.  Our code never changes these
+   global variables from default.  If something else in the user's
+   program does, User is responsible for making sure it doesn't
+   interfere with our use of the library.
+
+   Note that when we say what the Curl library does, we're also
+   talking about various other libraries Curl uses internally, and in
+   fact much of what we're saying about global variables springs from
+   such subordinate libraries as OpenSSL and Winsock.
+-----------------------------------------------------------------------------*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/time.h>
+
+#include "xmlrpc_config.h"
+
+#include "bool.h"
+#include "girmath.h"
+#include "mallocvar.h"
+#include "linklist.h"
+#include "girstring.h"
+#include "pthreadx.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/client_int.h"
+#include "xmlrpc-c/transport.h"
+#include "version.h"
+
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+#include <curl/multi.h>
+
+#if defined (WIN32) && defined(_DEBUG)
+#  include <crtdbg.h>
+#  define new DEBUG_NEW
+#  define malloc(size) _malloc_dbg( size, _NORMAL_BLOCK, __FILE__, __LINE__)
+#  undef THIS_FILE
+   static char THIS_FILE[] = __FILE__;
+#endif /*WIN32 && _DEBUG*/
+
+
+
+struct curlSetup {
+
+    /* This is all client transport properties that are implemented as
+       simple Curl session properties (i.e. the transport basically just
+       passes them through to Curl without looking at them).
+
+       People occasionally want to replace all this with something where
+       the Xmlrpc-c user simply does the curl_easy_setopt() call and this
+       code need not know about all these options.  Unfortunately, that's
+       a significant modularity violation.  Either the Xmlrpc-c user
+       controls the Curl object or he doesn't.  If he does, then he
+       shouldn't use libxmlrpc_client -- he should just copy some of this
+       code into his own program.  If he doesn't, then he should never see
+       the Curl library.
+
+       Speaking of modularity: the only reason this is a separate struct
+       is to make the code easier to manage.  Ideally, the fact that these
+       particular properties of the transport are implemented by simple
+       Curl session setup would be known only at the lowest level code
+       that does that setup.
+    */
+
+    const char * networkInterface;
+        /* This identifies the network interface on the local side to
+           use for the session.  It is an ASCIIZ string in the form
+           that the Curl recognizes for setting its CURLOPT_INTERFACE
+           option (also the --interface option of the Curl program).
+           E.g. "9.1.72.189" or "giraffe-data.com" or "eth0".  
+
+           It isn't necessarily valid, but it does have a terminating NUL.
+
+           NULL means we have no preference.
+        */
+    xmlrpc_bool sslVerifyPeer;
+        /* In an SSL connection, we should authenticate the server's SSL
+           certificate -- refuse to talk to him if it isn't authentic.
+           This is equivalent to Curl's CURLOPT_SSL_VERIFY_PEER option.
+        */
+    xmlrpc_bool sslVerifyHost;
+        /* In an SSL connection, we should verify that the server's
+           certificate (independently of whether the certificate is
+           authentic) indicates the host name that is in the URL we
+           are using for the server.
+        */
+
+    const char * sslCert;
+    const char * sslCertType;
+    const char * sslCertPasswd;
+    const char * sslKey;
+    const char * sslKeyType;
+    const char * sslKeyPasswd;
+    const char * sslEngine;
+    bool         sslEngineDefault;
+    unsigned int sslVersion;
+    const char * caInfo;
+    const char * caPath;
+    const char * randomFile;
+    const char * egdSocket;
+    const char * sslCipherList;
+};
+
+
+/*============================================================================
+      locks
+==============================================================================
+   This is the beginnings of a lock abstraction that will allow this
+   transport to be used with locks other than pthread locks
+============================================================================*/
+
+struct lock {
+    pthread_mutex_t theLock;
+    void (*lock)(struct lock *);
+    void (*unlock)(struct lock *);
+    void (*destroy)(struct lock *);
+};
+
+typedef struct lock lock;
+
+static void
+lock_pthread(struct lock * const lockP) {
+    pthread_mutex_lock(&lockP->theLock);
+}
+
+static void
+unlock_pthread(struct lock * const lockP) {
+    pthread_mutex_unlock(&lockP->theLock);
+}
+
+static void
+destroyLock_pthread(struct lock * const lockP) {
+    pthread_mutex_destroy(&lockP->theLock);
+    free(lockP);
+}
+
+
+static struct lock *
+createLock_pthread(void) {
+    struct lock * lockP;
+    MALLOCVAR(lockP);
+    if (lockP) {
+        pthread_mutex_init(&lockP->theLock, NULL);
+        lockP->lock    = &lock_pthread;
+        lockP->unlock  = &unlock_pthread;
+        lockP->destroy = &destroyLock_pthread;
+    }
+    return lockP;
+}
+
+
+
+
+/*=============================================================================
+    curlMulti
+=============================================================================*/
+
+struct curlMulti {
+/*----------------------------------------------------------------------------
+   This is an extension to Curl's CURLM object.  The extensions are:
+
+   1) It has a lock so multiple threads can use it simultaneously.
+
+   2) Its "select" file descriptor vectors are self-contained.  CURLM
+      requires the user to maintain them separately.
+-----------------------------------------------------------------------------*/
+    CURLM * curlMultiP;
+    lock * lockP;
+        /* Hold this lock while accessing or using *curlMultiP.  You're
+           using the multi manager whenever you're calling a Curl
+           library multi manager function.
+        */
+    /* The following file descriptor sets are an integral part of the
+       CURLM object; Our curlMulti_fdset() routine binds them to the
+       CURLM object, and said object expects us to use them in a very
+       specific way, including doing a select() on them.  It is very,
+       very messy.
+    */
+    fd_set readFdSet;
+    fd_set writeFdSet;
+    fd_set exceptFdSet;
+};
+
+
+
+static struct curlMulti *
+createCurlMulti(void) {
+
+    struct curlMulti * retval;
+    struct curlMulti * curlMultiP;
+
+    MALLOCVAR(curlMultiP);
+
+    if (curlMultiP == NULL)
+        retval = NULL;
+    else {
+        curlMultiP->lockP = createLock_pthread();
+
+        if (curlMultiP->lockP == NULL)
+            retval = NULL;
+        else {
+            curlMultiP->curlMultiP = curl_multi_init();
+            if (curlMultiP->curlMultiP == NULL)
+                retval = NULL;
+            else
+                retval = curlMultiP;
+
+            if (retval == NULL)
+                curlMultiP->lockP->destroy(curlMultiP->lockP);
+        }
+        if (retval == NULL)
+            free(curlMultiP);
+    }
+    return retval;
+}
+
+
+
+static void
+destroyCurlMulti(struct curlMulti * const curlMultiP) {
+
+    curl_multi_cleanup(curlMultiP->curlMultiP);
+    
+    curlMultiP->lockP->destroy(curlMultiP->lockP);
+
+    free(curlMultiP);
+}
+
+
+
+static void
+curlMulti_perform(xmlrpc_env *       const envP,
+                  struct curlMulti * const curlMultiP,
+                  bool *             const immediateWorkToDoP,
+                  int *              const runningHandlesP) {
+
+    CURLMcode rc;
+
+    curlMultiP->lockP->lock(curlMultiP->lockP);
+
+    rc = curl_multi_perform(curlMultiP->curlMultiP, runningHandlesP);
+
+    curlMultiP->lockP->unlock(curlMultiP->lockP);
+
+    if (rc == CURLM_CALL_MULTI_PERFORM) {
+        *immediateWorkToDoP = true;
+    } else {
+        *immediateWorkToDoP = false;
+
+        if (rc != CURLM_OK) {
+            xmlrpc_faultf(envP,
+                          "Impossible failure of curl_multi_perform() "
+                          "with rc %d", rc);
+        }
+    }
+}        
+
+
+
+static void
+curlMulti_addHandle(xmlrpc_env *       const envP,
+                    struct curlMulti * const curlMultiP,
+                    CURL *             const curlSessionP) {
+
+    CURLMcode rc;
+
+    curlMultiP->lockP->lock(curlMultiP->lockP);
+
+    rc = curl_multi_add_handle(curlMultiP->curlMultiP, curlSessionP);
+    
+    curlMultiP->lockP->unlock(curlMultiP->lockP);
+
+    if (rc != CURLM_OK)
+        xmlrpc_faultf(envP, "Could not add Curl session to the "
+                      "curl multi manager.  curl_multi_add_handle() "
+                      "returns error code %d", rc);
+}
+
+
+static void
+curlMulti_removeHandle(struct curlMulti * const curlMultiP,
+                       CURL *             const curlSessionP) {
+
+    curlMultiP->lockP->lock(curlMultiP->lockP);
+
+    curl_multi_remove_handle(curlMultiP->curlMultiP, curlSessionP);
+    
+    curlMultiP->lockP->unlock(curlMultiP->lockP);
+}
+
+
+
+static void
+curlMulti_getMessage(struct curlMulti * const curlMultiP,
+                     bool *             const endOfMessagesP,
+                     CURLMsg *          const curlMsgP) {
+/*----------------------------------------------------------------------------
+   Get the next message from the queue of things the Curl multi manager
+   wants to say to us.
+
+   Return the message as *curlMsgP.
+
+   Iff there are no messages in the queue, return *endOfMessagesP == true.
+-----------------------------------------------------------------------------*/
+    int remainingMsgCount;
+    CURLMsg * privateCurlMsgP;
+        /* Note that this is a pointer into the multi manager's memory,
+           so we have to use it under lock.
+        */
+
+    curlMultiP->lockP->lock(curlMultiP->lockP);
+    
+    privateCurlMsgP = curl_multi_info_read(curlMultiP->curlMultiP,
+                                           &remainingMsgCount);
+        
+    if (privateCurlMsgP == NULL)
+        *endOfMessagesP = true;
+    else {
+        *endOfMessagesP = false;
+        *curlMsgP = *privateCurlMsgP;
+    }    
+    curlMultiP->lockP->unlock(curlMultiP->lockP);
+}
+
+
+
+static void
+curlMulti_fdset(xmlrpc_env *       const envP,
+                struct curlMulti * const curlMultiP,
+                fd_set *           const readFdSetP,
+                fd_set *           const writeFdSetP,
+                fd_set *           const exceptFdSetP,
+                int *              const maxFdP) {
+/*----------------------------------------------------------------------------
+   Set the CURLM object's file descriptor sets to those in the
+   curlMulti object, update those file descriptor sets with the
+   current needs of the multi manager, and return the resulting values
+   of the file descriptor sets.
+
+   This is a bizarre operation, but is necessary because of the nonmodular
+   way in which the Curl multi interface works with respect to waiting
+   for work with select().
+-----------------------------------------------------------------------------*/
+    CURLMcode rc;
+    
+    curlMultiP->lockP->lock(curlMultiP->lockP);
+
+    /* curl_multi_fdset() doesn't _set_ the fdsets.  It adds to existing
+       ones (so you can easily do a select() on other fds and Curl
+       fds at the same time).  So we have to clear first:
+    */
+    FD_ZERO(&curlMultiP->readFdSet);
+    FD_ZERO(&curlMultiP->writeFdSet);
+    FD_ZERO(&curlMultiP->exceptFdSet);
+
+    /* WARNING: curl_multi_fdset() doesn't just update the fdsets pointed
+       to by its arguments.  It makes the CURLM object remember those
+       pointers and refer back to them later!  In fact, curl_multi_perform
+       expects its caller to have done a select() on those masks.  No,
+       really.  The man page even admits it.
+    */
+
+    rc = curl_multi_fdset(curlMultiP->curlMultiP,
+                          &curlMultiP->readFdSet,
+                          &curlMultiP->writeFdSet,
+                          &curlMultiP->exceptFdSet,
+                          maxFdP);
+
+    *readFdSetP   = curlMultiP->readFdSet;
+    *writeFdSetP  = curlMultiP->writeFdSet;
+    *exceptFdSetP = curlMultiP->exceptFdSet;
+
+    curlMultiP->lockP->unlock(curlMultiP->lockP);
+
+    if (rc != CURLM_OK)
+        xmlrpc_faultf(envP, "Impossible failure of curl_multi_fdset() "
+                      "with rc %d", rc);
+}
+
+
+
+static void
+curlMulti_updateFdSet(struct curlMulti * const curlMultiP,
+                      fd_set             const readFdSet,
+                      fd_set             const writeFdSet,
+                      fd_set             const exceptFdSet) {
+/*----------------------------------------------------------------------------
+   curl_multi_perform() expects the file descriptor sets, which were bound
+   to the CURLM object via a prior curlMulti_fdset(), to contain the results
+   of a recent select().  This subroutine provides you a way to supply those.
+-----------------------------------------------------------------------------*/
+    curlMultiP->readFdSet   = readFdSet;
+    curlMultiP->writeFdSet  = writeFdSet;
+    curlMultiP->exceptFdSet = exceptFdSet;
+}
+
+                      
+
+/*===========================================================================*/
+
+
+struct xmlrpc_client_transport {
+    struct curlMulti * curlMultiP;
+        /* The Curl multi manager that this transport uses to handle
+           multiple Curl sessions at the same time.
+        */
+    CURL * syncCurlSessionP;
+        /* Handle for a Curl library session object that we use for
+           all synchronous RPCs.  An async RPC has one of its own,
+           and consequently does not share things such as persistent
+           connections and cookies with any other RPC.
+        */
+    lock * syncCurlSessionLockP;
+        /* Hold this lock while accessing or using *syncCurlSessionP.
+           You're using the session from the time you set any
+           attributes in it or start a transaction with it until any
+           transaction has finished and you've lost interest in any
+           attributes of the session.
+        */
+    const char * userAgent;
+        /* Prefix for the User-Agent HTTP header, reflecting facilities
+           outside of Xmlrpc-c.  The actual User-Agent header consists
+           of this prefix plus information about Xmlrpc-c.  NULL means
+           none.
+
+           This is constant.
+        */
+    struct curlSetup curlSetupStuff;
+        /* This is constant */
+};
+
+typedef struct {
+    /* This is all stuff that really ought to be in a Curl object, but
+       the Curl library is a little too simple for that.  So we build
+       a layer on top of Curl, and define this "transaction," as an
+       object subordinate to a Curl "session."  A Curl session has
+       zero or one transactions in progress.  The Curl session
+       "private data" is a pointer to the CurlTransaction object for
+       the current transaction.
+    */
+    CURL * curlSessionP;
+        /* Handle for the Curl session that hosts this transaction.
+           Note that only one transaction at a time can use a particular
+           Curl session, so this had better not be a session that some other
+           transaction is using simultaneously.
+        */
+    struct curlMulti * curlMultiP;
+        /* The Curl multi manager which manages the above curl session,
+           if any.  An asynchronous process uses a Curl multi manager
+           to manage the in-progress Curl sessions and thereby in-progress
+           RPCs.  A synchronous process has no need of a Curl multi manager.
+        */
+    struct rpc * rpcP;
+        /* The RPC which this transaction serves.  (If this structure
+           were a true extension of the Curl library as described above,
+           this would be a void *, since the Curl library doesn't know what
+           an RPC is, but since we use it only for that, we might as well
+           use the specific type here).
+        */
+    char curlError[CURL_ERROR_SIZE];
+        /* Error message from Curl */
+    struct curl_slist * headerList;
+        /* The HTTP headers for the transaction */
+    const char * serverUrl;  /* malloc'ed - belongs to this object */
+} curlTransaction;
+
+
+
+typedef struct rpc {
+    curlTransaction * curlTransactionP;
+        /* The object which does the HTTP transaction, with no knowledge
+           of XML-RPC or Xmlrpc-c.
+        */
+    xmlrpc_mem_block * responseXmlP;
+        /* Where the response XML for this RPC should go or has gone. */
+    xmlrpc_transport_asynch_complete complete;
+        /* Routine to call to complete the RPC after it is complete HTTP-wise.
+           NULL if none.
+        */
+    struct xmlrpc_call_info * callInfoP;
+        /* User's identifier for this RPC */
+} rpc;
+
+
+static int
+timeDiffMillisec(struct timeval const minuend,
+                 struct timeval const subtractor) {
+
+    return (minuend.tv_sec - subtractor.tv_sec) * 1000 +
+        (minuend.tv_usec - subtractor.tv_usec + 500) / 1000;
+}
+
+
+
+static bool
+timeIsAfter(struct timeval const comparator,
+            struct timeval const comparand) {
+
+    if (comparator.tv_sec > comparand.tv_sec)
+        return true;
+    else if (comparator.tv_sec < comparand.tv_sec)
+        return false;
+    else {
+        /* Seconds are equal */
+        if (comparator.tv_usec > comparand.tv_usec)
+            return true;
+        else
+            return false;
+    }
+}
+
+
+
+static void
+addMilliseconds(struct timeval   const addend,
+                unsigned int     const adder,
+                struct timeval * const sumP) {
+
+    unsigned int newRawUsec;
+
+    newRawUsec = addend.tv_usec + adder * 1000;
+
+    sumP->tv_sec  = addend.tv_sec + newRawUsec / 1000000;
+    sumP->tv_usec = newRawUsec % 1000000;
+}
+
+
+
+static void
+lockSyncCurlSession(struct xmlrpc_client_transport * const transportP) {
+    transportP->syncCurlSessionLockP->lock(transportP->syncCurlSessionLockP);
+}
+
+
+
+static void
+unlockSyncCurlSession(struct xmlrpc_client_transport * const transportP) {
+    transportP->syncCurlSessionLockP->unlock(transportP->syncCurlSessionLockP);
+}
+
+
+
+static size_t 
+collect(void *  const ptr, 
+        size_t  const size, 
+        size_t  const nmemb,  
+        FILE  * const stream) {
+/*----------------------------------------------------------------------------
+   This is a Curl output function.  Curl calls this to deliver the
+   HTTP response body.  Curl thinks it's writing to a POSIX stream.
+-----------------------------------------------------------------------------*/
+    xmlrpc_mem_block * const responseXmlP = (xmlrpc_mem_block *) stream;
+    char * const buffer = ptr;
+    size_t const length = nmemb * size;
+
+    size_t retval;
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+    xmlrpc_mem_block_append(&env, responseXmlP, buffer, length);
+    if (env.fault_occurred)
+        retval = (size_t)-1;
+    else
+        /* Really?  Shouldn't it be like fread() and return 'nmemb'? */
+        retval = length;
+    
+    return retval;
+}
+
+
+
+static void
+initWindowsStuff(xmlrpc_env * const envP ATTR_UNUSED) {
+
+#if defined (WIN32)
+    /* This is CRITICAL so that cURL-Win32 works properly! */
+    
+    /* So this commenter says, but I wonder why.  libcurl should do the
+       required WSAStartup() itself, and it looks to me like it does.
+       -Bryan 06.01.01
+    */
+    WORD wVersionRequested;
+    WSADATA wsaData;
+    int err;
+    wVersionRequested = MAKEWORD(1, 1);
+    
+    err = WSAStartup(wVersionRequested, &wsaData);
+    if (err)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "Winsock startup failed.  WSAStartup returned rc %d", err);
+    else {
+        if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
+            /* Tell the user that we couldn't find a useable */ 
+            /* winsock.dll. */ 
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR, "Winsock reported that "
+                "it does not implement the requested version 1.1.");
+        }
+        if (envP->fault_occurred)
+            WSACleanup();
+    }
+#endif
+}
+
+
+
+static void
+termWindowsStuff(void) {
+
+#if defined (WIN32)
+    WSACleanup();
+#endif
+}
+
+
+
+static void
+getXportParms(xmlrpc_env *  const envP ATTR_UNUSED,
+              const struct xmlrpc_curl_xportparms * const curlXportParmsP,
+              size_t        const parmSize,
+              struct xmlrpc_client_transport * const transportP) {
+/*----------------------------------------------------------------------------
+   Get the parameters out of *curlXportParmsP and update *transportP
+   to reflect them.
+
+   *curlXportParmsP is a 'parmSize' bytes long prefix of
+   struct xmlrpc_curl_xportparms.
+
+   curlXportParmsP is something the user created.  It's designed to be
+   friendly to the user, not to this program, and is encumbered by
+   lots of backward compatibility constraints.  In particular, the
+   user may have coded and/or compiled it at a time that struct
+   xmlrpc_curl_xportparms was smaller than it is now!
+
+   So that's why we don't simply attach a copy of *curlXportParmsP to
+   *transportP.
+
+   To the extent that *curlXportParmsP is too small to contain a parameter,
+   we return the default value for that parameter.
+
+   Special case:  curlXportParmsP == NULL means there is no input at all.
+   In that case, we return default values for everything.
+-----------------------------------------------------------------------------*/
+    struct curlSetup * const curlSetupP = &transportP->curlSetupStuff;
+
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(user_agent))
+        transportP->userAgent = NULL;
+    else if (curlXportParmsP->user_agent == NULL)
+        transportP->userAgent = NULL;
+    else
+        transportP->userAgent = strdup(curlXportParmsP->user_agent);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(network_interface))
+        curlSetupP->networkInterface = NULL;
+    else if (curlXportParmsP->network_interface == NULL)
+        curlSetupP->networkInterface = NULL;
+    else
+        curlSetupP->networkInterface =
+            strdup(curlXportParmsP->network_interface);
+
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(no_ssl_verifypeer))
+        curlSetupP->sslVerifyPeer = true;
+    else
+        curlSetupP->sslVerifyPeer = !curlXportParmsP->no_ssl_verifypeer;
+        
+    if (!curlXportParmsP || 
+        parmSize < XMLRPC_CXPSIZE(no_ssl_verifyhost))
+        curlSetupP->sslVerifyHost = true;
+    else
+        curlSetupP->sslVerifyHost = !curlXportParmsP->no_ssl_verifyhost;
+
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(ssl_cert))
+        curlSetupP->sslCert = NULL;
+    else if (curlXportParmsP->ssl_cert == NULL)
+        curlSetupP->sslCert = NULL;
+    else
+        curlSetupP->sslCert = strdup(curlXportParmsP->ssl_cert);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslcerttype))
+        curlSetupP->sslCertType = NULL;
+    else if (curlXportParmsP->sslcerttype == NULL)
+        curlSetupP->sslCertType = NULL;
+    else
+        curlSetupP->sslCertType = strdup(curlXportParmsP->sslcerttype);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslcertpasswd))
+        curlSetupP->sslCertPasswd = NULL;
+    else if (curlXportParmsP->sslcertpasswd == NULL)
+        curlSetupP->sslCertPasswd = NULL;
+    else
+        curlSetupP->sslCertPasswd = strdup(curlXportParmsP->sslcertpasswd);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkey))
+        curlSetupP->sslKey = NULL;
+    else if (curlXportParmsP->sslkey == NULL)
+        curlSetupP->sslKey = NULL;
+    else
+        curlSetupP->sslKey = strdup(curlXportParmsP->sslkey);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkeytype))
+        curlSetupP->sslKeyType = NULL;
+    else if (curlXportParmsP->sslkeytype == NULL)
+        curlSetupP->sslKeyType = NULL;
+    else
+        curlSetupP->sslKeyType = strdup(curlXportParmsP->sslkeytype);
+    
+        if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslkeypasswd))
+        curlSetupP->sslKeyPasswd = NULL;
+    else if (curlXportParmsP->sslkeypasswd == NULL)
+        curlSetupP->sslKeyPasswd = NULL;
+    else
+        curlSetupP->sslKeyPasswd = strdup(curlXportParmsP->sslkeypasswd);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslengine))
+        curlSetupP->sslEngine = NULL;
+    else if (curlXportParmsP->sslengine == NULL)
+        curlSetupP->sslEngine = NULL;
+    else
+        curlSetupP->sslEngine = strdup(curlXportParmsP->sslengine);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslengine_default))
+        curlSetupP->sslEngineDefault = false;
+    else
+        curlSetupP->sslEngineDefault = !!curlXportParmsP->sslengine_default;
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(sslversion))
+        curlSetupP->sslVersion = XMLRPC_SSLVERSION_DEFAULT;
+    else
+        curlSetupP->sslVersion = curlXportParmsP->sslversion;
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(cainfo))
+        curlSetupP->caInfo = NULL;
+    else if (curlXportParmsP->cainfo == NULL)
+        curlSetupP->caInfo = NULL;
+    else
+        curlSetupP->caInfo = strdup(curlXportParmsP->cainfo);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(capath))
+        curlSetupP->caPath = NULL;
+    else if (curlXportParmsP->capath == NULL)
+        curlSetupP->caPath = NULL;
+    else
+        curlSetupP->caPath = strdup(curlXportParmsP->capath);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(randomfile))
+        curlSetupP->randomFile = NULL;
+    else if (curlXportParmsP->randomfile == NULL)
+        curlSetupP->randomFile = NULL;
+    else
+        curlSetupP->randomFile = strdup(curlXportParmsP->randomfile);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(egdsocket))
+        curlSetupP->egdSocket = NULL;
+    else if (curlXportParmsP->egdsocket == NULL)
+        curlSetupP->egdSocket = NULL;
+    else
+        curlSetupP->egdSocket = strdup(curlXportParmsP->egdsocket);
+    
+    if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(ssl_cipher_list))
+        curlSetupP->sslCipherList = NULL;
+    else if (curlXportParmsP->ssl_cipher_list == NULL)
+        curlSetupP->sslCipherList = NULL;
+    else
+        curlSetupP->sslCipherList = strdup(curlXportParmsP->ssl_cipher_list);
+
+}
+
+
+
+static void
+freeXportParms(const struct xmlrpc_client_transport * const transportP) {
+
+    const struct curlSetup * const curlSetupP = &transportP->curlSetupStuff;
+
+    if (curlSetupP->sslCipherList)
+        xmlrpc_strfree(curlSetupP->sslCipherList);
+    if (curlSetupP->egdSocket)
+        xmlrpc_strfree(curlSetupP->egdSocket);
+    if (curlSetupP->randomFile)
+        xmlrpc_strfree(curlSetupP->randomFile);
+    if (curlSetupP->caPath)
+        xmlrpc_strfree(curlSetupP->caPath);
+    if (curlSetupP->caInfo)
+        xmlrpc_strfree(curlSetupP->caInfo);
+    if (curlSetupP->sslEngine)
+        xmlrpc_strfree(curlSetupP->sslEngine);
+    if (curlSetupP->sslKeyPasswd)
+        xmlrpc_strfree(curlSetupP->sslKeyPasswd);
+    if (curlSetupP->sslKeyType)
+        xmlrpc_strfree(curlSetupP->sslKeyType);
+    if (curlSetupP->sslKey)
+        xmlrpc_strfree(curlSetupP->sslKey);
+    if (curlSetupP->sslCertPasswd)
+        xmlrpc_strfree(curlSetupP->sslCertPasswd);
+    if (curlSetupP->sslCertType)
+        xmlrpc_strfree(curlSetupP->sslCertType);
+    if (curlSetupP->sslCert)
+        xmlrpc_strfree(curlSetupP->sslCert);
+    if (curlSetupP->networkInterface)
+        xmlrpc_strfree(curlSetupP->networkInterface);
+    if (transportP->userAgent)
+        xmlrpc_strfree(transportP->userAgent);
+}
+
+
+
+static void
+createSyncCurlSession(xmlrpc_env * const envP,
+                      CURL **      const curlSessionPP) {
+/*----------------------------------------------------------------------------
+   Create a Curl session to be used for multiple serial transactions.
+   The Curl session we create is not complete -- it still has to be
+   further set up for each particular transaction.
+
+   We can't set up anything here that changes from one transaction to the
+   next.
+
+   We don't bother setting up anything that has to be set up for an
+   asynchronous transaction because code that is common between synchronous
+   and asynchronous transactions takes care of that anyway.
+
+   That leaves things, such as cookies, that don't exist for
+   asynchronous transactions, and are common to multiple serial
+   synchronous transactions.
+-----------------------------------------------------------------------------*/
+    CURL * const curlSessionP = curl_easy_init();
+
+    if (curlSessionP == NULL)
+        xmlrpc_faultf(envP, "Could not create Curl session.  "
+                      "curl_easy_init() failed.");
+    else {
+        /* The following is a trick.  CURLOPT_COOKIEFILE is the name
+           of the file containing the initial cookies for the Curl
+           session.  But setting it is also what turns on the cookie
+           function itself, whereby the Curl library accepts and
+           stores cookies from the server and sends them back on
+           future requests.  We don't have a file of initial cookies, but
+           we want to turn on cookie function, so we set the option to
+           something we know does not validly name a file.  Curl will
+           ignore the error and just start up cookie function with no
+           initial cookies.
+        */
+        curl_easy_setopt(curlSessionP, CURLOPT_COOKIEFILE, "");
+
+        *curlSessionPP = curlSessionP;
+    }
+}
+
+
+
+static void
+destroySyncCurlSession(CURL * const curlSessionP) {
+
+    curl_easy_cleanup(curlSessionP);
+}
+
+
+
+static void
+makeSyncCurlSession(xmlrpc_env *                     const envP,
+                    struct xmlrpc_client_transport * const transportP) {
+
+    transportP->syncCurlSessionLockP = createLock_pthread();
+    if (transportP->syncCurlSessionLockP == NULL)
+        xmlrpc_faultf(envP, "Unable to create lock for "
+                      "synchronous Curl session.");
+    else {
+        createSyncCurlSession(envP, &transportP->syncCurlSessionP);
+        if (envP->fault_occurred)
+            transportP->syncCurlSessionLockP->destroy(
+                transportP->syncCurlSessionLockP); 
+    }
+}
+
+
+
+static void
+unmakeSyncCurlSession(struct xmlrpc_client_transport * const transportP) {
+
+    destroySyncCurlSession(transportP->syncCurlSessionP);
+
+    transportP->syncCurlSessionLockP->destroy(
+        transportP->syncCurlSessionLockP); 
+}
+
+
+
+static void
+assertConstantsMatch(void) {
+/*----------------------------------------------------------------------------
+   There are some constants that we define as part of the Xmlrpc-c
+   interface that are identical to constants in the Curl interface to
+   make curl option setting work.  This function asserts such
+   formally.
+-----------------------------------------------------------------------------*/
+    assert(XMLRPC_SSLVERSION_DEFAULT == CURL_SSLVERSION_DEFAULT);
+    assert(XMLRPC_SSLVERSION_TLSv1   == CURL_SSLVERSION_TLSv1);
+    assert(XMLRPC_SSLVERSION_SSLv2   == CURL_SSLVERSION_SSLv2);
+    assert(XMLRPC_SSLVERSION_SSLv3   == CURL_SSLVERSION_SSLv3);
+}
+
+
+
+static void 
+create(xmlrpc_env *                      const envP,
+       int                               const flags ATTR_UNUSED,
+       const char *                      const appname ATTR_UNUSED,
+       const char *                      const appversion ATTR_UNUSED,
+       const struct xmlrpc_xportparms *  const transportparmsP,
+       size_t                            const parm_size,
+       struct xmlrpc_client_transport ** const handlePP) {
+/*----------------------------------------------------------------------------
+   This does the 'create' operation for a Curl client transport.
+-----------------------------------------------------------------------------*/
+    struct xmlrpc_curl_xportparms * const curlXportParmsP = 
+        (struct xmlrpc_curl_xportparms *) transportparmsP;
+
+    struct xmlrpc_client_transport * transportP;
+
+    assertConstantsMatch();
+
+    MALLOCVAR(transportP);
+    if (transportP == NULL)
+        xmlrpc_faultf(envP, "Unable to allocate transport descriptor.");
+    else {
+        transportP->curlMultiP = createCurlMulti();
+        
+        if (transportP->curlMultiP == NULL)
+            xmlrpc_faultf(envP, "Unable to create Curl multi manager");
+        else {
+            getXportParms(envP, curlXportParmsP, parm_size, transportP);
+
+            if (!envP->fault_occurred) {
+                makeSyncCurlSession(envP, transportP);
+
+                if (envP->fault_occurred)
+                    freeXportParms(transportP);
+            }
+            if (envP->fault_occurred)
+                destroyCurlMulti(transportP->curlMultiP);
+        }                 
+        if (envP->fault_occurred)
+            free(transportP);
+    }
+    *handlePP = transportP;
+}
+
+
+
+static void
+assertNoOutstandingCurlWork(struct curlMulti * const curlMultiP) {
+
+    xmlrpc_env env;
+    bool immediateWorkToDo;
+    int runningHandles;
+    
+    xmlrpc_env_init(&env);
+    
+    curlMulti_perform(&env, curlMultiP, &immediateWorkToDo, &runningHandles);
+    
+    /* We know the above was a no-op, since we're asserting that there
+       is no outstanding work.
+    */
+    XMLRPC_ASSERT(!env.fault_occurred);
+    XMLRPC_ASSERT(!immediateWorkToDo);
+    XMLRPC_ASSERT(runningHandles == 0);
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void 
+destroy(struct xmlrpc_client_transport * const clientTransportP) {
+/*----------------------------------------------------------------------------
+   This does the 'destroy' operation for a Curl client transport.
+-----------------------------------------------------------------------------*/
+    XMLRPC_ASSERT(clientTransportP != NULL);
+
+    assertNoOutstandingCurlWork(clientTransportP->curlMultiP);
+        /* We know this is true because a condition of destroying the
+           transport is that there be no outstanding RPCs.
+        */
+    unmakeSyncCurlSession(clientTransportP);
+
+    destroyCurlMulti(clientTransportP->curlMultiP);
+
+    freeXportParms(clientTransportP);
+
+    free(clientTransportP);
+}
+
+
+
+static void
+addHeader(xmlrpc_env * const envP,
+          struct curl_slist ** const headerListP,
+          const char *         const headerText) {
+
+    struct curl_slist * newHeaderList;
+    newHeaderList = curl_slist_append(*headerListP, headerText);
+    if (newHeaderList == NULL)
+        xmlrpc_faultf(envP,
+                      "Could not add header '%s'.  "
+                      "curl_slist_append() failed.", headerText);
+    else
+        *headerListP = newHeaderList;
+}
+
+
+
+static void
+addContentTypeHeader(xmlrpc_env *         const envP,
+                     struct curl_slist ** const headerListP) {
+    
+    addHeader(envP, headerListP, "Content-Type: text/xml");
+}
+
+
+
+static void
+addUserAgentHeader(xmlrpc_env *         const envP,
+                   struct curl_slist ** const headerListP,
+                   const char *         const userAgent) {
+    
+    if (userAgent) {
+        curl_version_info_data * const curlInfoP =
+            curl_version_info(CURLVERSION_NOW);
+        char curlVersion[32];
+        const char * userAgentHeader;
+        
+        snprintf(curlVersion, sizeof(curlVersion), "%u.%u.%u",
+                (curlInfoP->version_num >> 16) && 0xff,
+                (curlInfoP->version_num >>  8) && 0xff,
+                (curlInfoP->version_num >>  0) && 0xff
+            );
+                  
+        xmlrpc_asprintf(&userAgentHeader,
+                        "User-Agent: %s Xmlrpc-c/%s Curl/%s",
+                        userAgent, XMLRPC_C_VERSION, curlVersion);
+        
+        if (userAgentHeader == xmlrpc_strsol)
+            xmlrpc_faultf(envP, "Couldn't allocate memory for "
+                          "User-Agent header");
+        else {
+            addHeader(envP, headerListP, userAgentHeader);
+            
+            xmlrpc_strfree(userAgentHeader);
+        }
+    }
+}
+
+
+
+static void
+addAuthorizationHeader(xmlrpc_env *         const envP,
+                       struct curl_slist ** const headerListP,
+                       const char *         const basicAuthInfo) {
+
+    if (basicAuthInfo) {
+        const char * authorizationHeader;
+            
+        xmlrpc_asprintf(&authorizationHeader, "Authorization: %s",
+                        basicAuthInfo);
+            
+        if (authorizationHeader == xmlrpc_strsol)
+            xmlrpc_faultf(envP, "Couldn't allocate memory for "
+                          "Authorization header");
+        else {
+            addHeader(envP, headerListP, authorizationHeader);
+
+            xmlrpc_strfree(authorizationHeader);
+        }
+    }
+}
+
+
+
+static void
+createCurlHeaderList(xmlrpc_env *               const envP,
+                     const xmlrpc_server_info * const serverP,
+                     const char *               const userAgent,
+                     struct curl_slist **       const headerListP) {
+
+    struct curl_slist * headerList;
+
+    headerList = NULL;  /* initial value - empty list */
+
+    addContentTypeHeader(envP, &headerList);
+    if (!envP->fault_occurred) {
+        addUserAgentHeader(envP, &headerList, userAgent);
+        if (!envP->fault_occurred) {
+            addAuthorizationHeader(envP, &headerList, 
+                                   serverP->_http_basic_auth);
+        }
+    }
+    if (envP->fault_occurred)
+        curl_slist_free_all(headerList);
+    else
+        *headerListP = headerList;
+}
+
+
+
+static void
+setupCurlSession(xmlrpc_env *             const envP,
+                 curlTransaction *        const curlTransactionP,
+                 xmlrpc_mem_block *       const callXmlP,
+                 xmlrpc_mem_block *       const responseXmlP,
+                 const struct curlSetup * const curlSetupP) {
+/*----------------------------------------------------------------------------
+   Set up the Curl session for the transaction *curlTransactionP so that
+   a subsequent curl_easy_perform() will perform said transaction.
+-----------------------------------------------------------------------------*/
+    CURL * const curlSessionP = curlTransactionP->curlSessionP;
+
+    assertConstantsMatch();
+
+    curl_easy_setopt(curlSessionP, CURLOPT_POST, 1);
+    curl_easy_setopt(curlSessionP, CURLOPT_URL, curlTransactionP->serverUrl);
+
+    XMLRPC_MEMBLOCK_APPEND(char, envP, callXmlP, "\0", 1);
+    if (!envP->fault_occurred) {
+        curl_easy_setopt(curlSessionP, CURLOPT_POSTFIELDS, 
+                         XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP));
+        
+        curl_easy_setopt(curlSessionP, CURLOPT_WRITEFUNCTION, collect);
+        curl_easy_setopt(curlSessionP, CURLOPT_FILE, responseXmlP);
+        curl_easy_setopt(curlSessionP, CURLOPT_HEADER, 0);
+        curl_easy_setopt(curlSessionP, CURLOPT_ERRORBUFFER, 
+                         curlTransactionP->curlError);
+        curl_easy_setopt(curlSessionP, CURLOPT_NOPROGRESS, 1);
+        
+        curl_easy_setopt(curlSessionP, CURLOPT_HTTPHEADER, 
+                         curlTransactionP->headerList);
+
+        curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYPEER,
+                         curlSetupP->sslVerifyPeer);
+        curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYHOST,
+                         curlSetupP->sslVerifyHost ? 2 : 0);
+
+        if (curlSetupP->networkInterface)
+            curl_easy_setopt(curlSessionP, CURLOPT_INTERFACE,
+                             curlSetupP->networkInterface);
+        if (curlSetupP->sslCert)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLCERT,
+                             curlSetupP->sslCert);
+        if (curlSetupP->sslCertType)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLCERTTYPE,
+                             curlSetupP->sslCertType);
+        if (curlSetupP->sslCertPasswd)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLCERTPASSWD,
+                             curlSetupP->sslCertPasswd);
+        if (curlSetupP->sslKey)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLKEY,
+                             curlSetupP->sslKey);
+        if (curlSetupP->sslKeyType)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLKEYTYPE,
+                             curlSetupP->sslKeyType);
+        if (curlSetupP->sslKeyPasswd)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLKEYPASSWD,
+                             curlSetupP->sslKeyPasswd);
+        if (curlSetupP->sslEngine)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLENGINE,
+                             curlSetupP->sslEngine);
+        if (curlSetupP->sslEngineDefault)
+            /* 3rd argument seems to be required by some Curl */
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLENGINE_DEFAULT, 1l);
+        if (curlSetupP->sslVersion != XMLRPC_SSLVERSION_DEFAULT)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSLVERSION,
+                             curlSetupP->sslVersion);
+        if (curlSetupP->caInfo)
+            curl_easy_setopt(curlSessionP, CURLOPT_CAINFO,
+                             curlSetupP->caInfo);
+        if (curlSetupP->caPath)
+            curl_easy_setopt(curlSessionP, CURLOPT_CAPATH,
+                             curlSetupP->caPath);
+        if (curlSetupP->randomFile)
+            curl_easy_setopt(curlSessionP, CURLOPT_RANDOM_FILE,
+                             curlSetupP->randomFile);
+        if (curlSetupP->egdSocket)
+            curl_easy_setopt(curlSessionP, CURLOPT_EGDSOCKET,
+                             curlSetupP->egdSocket);
+        if (curlSetupP->sslCipherList)
+            curl_easy_setopt(curlSessionP, CURLOPT_SSL_CIPHER_LIST,
+                             curlSetupP->sslCipherList);
+    }
+}
+
+
+
+static void
+createCurlTransaction(xmlrpc_env *               const envP,
+                      CURL *                     const curlSessionP,
+                      struct curlMulti *         const curlMultiP,
+                      const xmlrpc_server_info * const serverP,
+                      xmlrpc_mem_block *         const callXmlP,
+                      xmlrpc_mem_block *         const responseXmlP,
+                      const char *               const userAgent,
+                      const struct curlSetup *   const curlSetupStuffP,
+                      rpc *                      const rpcP,
+                      curlTransaction **         const curlTransactionPP) {
+
+    curlTransaction * curlTransactionP;
+
+    MALLOCVAR(curlTransactionP);
+    if (curlTransactionP == NULL)
+        xmlrpc_faultf(envP, "No memory to create Curl transaction.");
+    else {
+        curlTransactionP->curlSessionP = curlSessionP;
+        curlTransactionP->curlMultiP   = curlMultiP;
+        curlTransactionP->rpcP         = rpcP;
+
+        curlTransactionP->serverUrl = strdup(serverP->_server_url);
+        if (curlTransactionP->serverUrl == NULL)
+            xmlrpc_faultf(envP, "Out of memory to store server URL.");
+        else {
+            createCurlHeaderList(envP, serverP, userAgent,
+                                 &curlTransactionP->headerList);
+            
+            if (!envP->fault_occurred)
+                setupCurlSession(envP, curlTransactionP,
+                                 callXmlP, responseXmlP,
+                                 curlSetupStuffP);
+
+            if (envP->fault_occurred)
+                xmlrpc_strfree(curlTransactionP->serverUrl);
+        }
+        if (envP->fault_occurred)
+            free(curlTransactionP);
+    }
+    *curlTransactionPP = curlTransactionP;
+}
+
+
+
+static void
+destroyCurlTransaction(curlTransaction * const curlTransactionP) {
+
+    curl_slist_free_all(curlTransactionP->headerList);
+    xmlrpc_strfree(curlTransactionP->serverUrl);
+
+    free(curlTransactionP);
+}
+
+
+
+static void
+getCurlTransactionError(curlTransaction * const curlTransactionP,
+                        xmlrpc_env *      const envP) {
+
+    CURLcode res;
+    long http_result;
+
+    res = curl_easy_getinfo(curlTransactionP->curlSessionP,
+                            CURLINFO_HTTP_CODE, &http_result);
+    
+    if (res != CURLE_OK)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, 
+            "Curl performed the HTTP POST request, but was "
+            "unable to say what the HTTP result code was.  "
+            "curl_easy_getinfo(CURLINFO_HTTP_CODE) says: %s", 
+            curlTransactionP->curlError);
+    else {
+        if (http_result != 200)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_NETWORK_ERROR, "HTTP response: %ld",
+                http_result);
+    }
+}
+
+
+
+static void
+performCurlTransaction(xmlrpc_env *      const envP,
+                       curlTransaction * const curlTransactionP) {
+
+    CURL * const curlSessionP = curlTransactionP->curlSessionP;
+
+    CURLcode res;
+
+    res = curl_easy_perform(curlSessionP);
+    
+    if (res != CURLE_OK)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_NETWORK_ERROR, "Curl failed to perform "
+            "HTTP POST request.  curl_easy_perform() says: %s", 
+            curlTransactionP->curlError);
+    else
+        getCurlTransactionError(curlTransactionP, envP);
+}
+
+
+
+static void
+createRpc(xmlrpc_env *                     const envP,
+          struct xmlrpc_client_transport * const clientTransportP,
+          CURL *                           const curlSessionP,
+          const xmlrpc_server_info *       const serverP,
+          xmlrpc_mem_block *               const callXmlP,
+          xmlrpc_mem_block *               const responseXmlP,
+          xmlrpc_transport_asynch_complete       complete, 
+          struct xmlrpc_call_info *        const callInfoP,
+          rpc **                           const rpcPP) {
+
+    rpc * rpcP;
+
+    MALLOCVAR(rpcP);
+    if (rpcP == NULL)
+        xmlrpc_faultf(envP, "Couldn't allocate memory for rpc object");
+    else {
+        rpcP->callInfoP    = callInfoP;
+        rpcP->complete     = complete;
+        rpcP->responseXmlP = responseXmlP;
+
+        createCurlTransaction(envP,
+                              curlSessionP,
+                              clientTransportP->curlMultiP,
+                              serverP,
+                              callXmlP, responseXmlP, 
+                              clientTransportP->userAgent,
+                              &clientTransportP->curlSetupStuff,
+                              rpcP,
+                              &rpcP->curlTransactionP);
+        if (!envP->fault_occurred) {
+            if (envP->fault_occurred)
+                destroyCurlTransaction(rpcP->curlTransactionP);
+        }
+        if (envP->fault_occurred)
+            free(rpcP);
+    }
+    *rpcPP = rpcP;
+}
+
+
+
+static void 
+destroyRpc(rpc * const rpcP) {
+
+    XMLRPC_ASSERT_PTR_OK(rpcP);
+
+    destroyCurlTransaction(rpcP->curlTransactionP);
+
+    free(rpcP);
+}
+
+
+
+static void
+performRpc(xmlrpc_env * const envP,
+           rpc *        const rpcP) {
+
+    performCurlTransaction(envP, rpcP->curlTransactionP);
+}
+
+
+
+static void
+startCurlTransaction(xmlrpc_env *      const envP,
+                     curlTransaction * const curlTransactionP) {
+
+    /* A Curl session is serial -- it processes zero or one transaction
+       at a time.  We use the "private" attribute of the Curl session to
+       indicate which transaction it is presently processing.  This is
+       important when the transaction finishes, because libcurl will just
+       tell us that something finished on a particular session, not that
+       a particular transaction finished.
+    */
+    curl_easy_setopt(curlTransactionP->curlSessionP, CURLOPT_PRIVATE,
+                     curlTransactionP);
+
+    curlMulti_addHandle(envP,
+                        curlTransactionP->curlMultiP,
+                        curlTransactionP->curlSessionP);
+}
+
+
+
+static void
+startRpc(xmlrpc_env * const envP,
+         rpc *        const rpcP) {
+
+    startCurlTransaction(envP, rpcP->curlTransactionP);
+}
+
+
+
+static void 
+sendRequest(xmlrpc_env *                     const envP, 
+            struct xmlrpc_client_transport * const clientTransportP,
+            const xmlrpc_server_info *       const serverP,
+            xmlrpc_mem_block *               const callXmlP,
+            xmlrpc_transport_asynch_complete       complete,
+            struct xmlrpc_call_info *        const callInfoP) {
+/*----------------------------------------------------------------------------
+   Initiate an XML-RPC rpc asynchronously.  Don't wait for it to go to
+   the server.
+
+   Unless we return failure, we arrange to have complete() called when
+   the rpc completes.
+
+   This does the 'send_request' operation for a Curl client transport.
+-----------------------------------------------------------------------------*/
+    rpc * rpcP;
+    xmlrpc_mem_block * responseXmlP;
+
+    responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+    if (!envP->fault_occurred) {
+        CURL * const curlSessionP = curl_easy_init();
+    
+        if (curlSessionP == NULL)
+            xmlrpc_faultf(envP, "Could not create Curl session.  "
+                          "curl_easy_init() failed.");
+        else {
+            createRpc(envP, clientTransportP, curlSessionP, serverP,
+                      callXmlP, responseXmlP, complete, callInfoP,
+                      &rpcP);
+            
+            if (!envP->fault_occurred) {
+                startRpc(envP, rpcP);
+                
+                if (envP->fault_occurred)
+                    destroyRpc(rpcP);
+            }
+            if (envP->fault_occurred)
+                curl_easy_cleanup(curlSessionP);
+        }
+        if (envP->fault_occurred)
+            XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
+    }
+    /* If we're returning success, the user's eventual finish_asynch
+       call will destroy this RPC, Curl session, and response buffer
+       and remove the Curl session from the Curl multi manager.
+       (If we're returning failure, we didn't create any of those).
+    */
+}
+
+
+
+static void
+finishCurlTransaction(xmlrpc_env * const envP ATTR_UNUSED,
+                      CURL *       const curlSessionP,
+                      CURLcode     const result) {
+/*----------------------------------------------------------------------------
+  Handle the event that a Curl transaction has completed on the Curl
+  session identified by 'curlSessionP'.
+
+  Tell the requester of the RPC which this transaction serves the
+  results.
+
+  Remove the Curl session from its Curl multi manager and destroy the
+  Curl session, the XML response buffer, the Curl transaction, and the RPC.
+-----------------------------------------------------------------------------*/
+    curlTransaction * curlTransactionP;
+    rpc * rpcP;
+
+    curl_easy_getinfo(curlSessionP, CURLINFO_PRIVATE, &curlTransactionP);
+
+    rpcP = curlTransactionP->rpcP;
+
+    curlMulti_removeHandle(curlTransactionP->curlMultiP,
+                           curlTransactionP->curlSessionP);
+    {
+        xmlrpc_env env;
+
+        xmlrpc_env_init(&env);
+
+        if (result != CURLE_OK) {
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_NETWORK_ERROR, "libcurl failed to execute the "
+                "HTTP POST transaction.  %s", curlTransactionP->curlError);
+        } else
+            getCurlTransactionError(curlTransactionP, &env);
+
+        rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env);
+
+        xmlrpc_env_clean(&env);
+    }
+
+    curl_easy_cleanup(curlSessionP);
+
+    XMLRPC_MEMBLOCK_FREE(char, rpcP->responseXmlP);
+
+    destroyRpc(rpcP);
+}
+
+
+
+static struct timeval
+selectTimeout(xmlrpc_timeoutType const timeoutType,
+              struct timeval     const timeoutTime) {
+/*----------------------------------------------------------------------------
+   Return the value that should be used in the select() call to wait for
+   there to be work for the Curl multi manager to do, given that the user
+   wants to timeout according to 'timeoutType' and 'timeoutTime'.
+-----------------------------------------------------------------------------*/
+    unsigned int selectTimeoutMillisec;
+    struct timeval retval;
+
+    selectTimeoutMillisec = 0; // quiet compiler warning
+
+    /* We assume there is work to do at least every 3 seconds, because
+       the Curl multi manager often has retries and other scheduled work
+       that doesn't involve file handles on which we can select().
+    */
+    switch (timeoutType) {
+    case timeout_no:
+        selectTimeoutMillisec = 3000;
+        break;
+    case timeout_yes: {
+        struct timeval nowTime;
+        int timeLeft;
+
+        gettimeofday(&nowTime, NULL);
+        timeLeft = timeDiffMillisec(timeoutTime, nowTime);
+
+        selectTimeoutMillisec = MIN(3000, MAX(0, timeLeft));
+    }
+    break;
+    }
+    retval.tv_sec = selectTimeoutMillisec / 1000;
+    retval.tv_usec = (selectTimeoutMillisec % 1000) * 1000;
+
+    return retval;
+}        
+
+
+
+static void
+processCurlMessages(xmlrpc_env *       const envP,
+                    struct curlMulti * const curlMultiP) {
+        
+    bool endOfMessages;
+
+    endOfMessages = false;   /* initial assumption */
+
+    while (!endOfMessages && !envP->fault_occurred) {
+        CURLMsg curlMsg;
+
+        curlMulti_getMessage(curlMultiP, &endOfMessages, &curlMsg);
+
+        if (!endOfMessages) {
+            if (curlMsg.msg == CURLMSG_DONE)
+                finishCurlTransaction(envP, curlMsg.easy_handle,
+                                      curlMsg.data.result);
+        }
+    }
+}
+
+
+
+static void
+waitForWork(xmlrpc_env *       const envP,
+            struct curlMulti * const curlMultiP,
+            xmlrpc_timeoutType const timeoutType,
+            struct timeval     const deadline) {
+    
+    fd_set readFdSet;
+    fd_set writeFdSet;
+    fd_set exceptFdSet;
+    int maxFd;
+
+    curlMulti_fdset(envP, curlMultiP,
+                    &readFdSet, &writeFdSet, &exceptFdSet, &maxFd);
+    if (!envP->fault_occurred) {
+        if (maxFd == -1) {
+            /* There are no Curl file descriptors on which to wait.
+               So either there's work to do right now or all transactions
+               are already complete.
+            */
+        } else {
+            struct timeval selectTimeoutArg;
+            int rc;
+            
+            selectTimeoutArg = selectTimeout(timeoutType, deadline);
+
+            rc = select(maxFd+1, &readFdSet, &writeFdSet, &exceptFdSet,
+                        &selectTimeoutArg);
+            
+            if (rc < 0)
+                xmlrpc_faultf(envP, "Impossible failure of select() "
+                              "with errno %d (%s)",
+                              errno, strerror(errno));
+            else {
+                /* Believe it or not, the Curl multi manager needs the
+                   results of our select().  So hand them over:
+                */
+                curlMulti_updateFdSet(curlMultiP,
+                                      readFdSet, writeFdSet, exceptFdSet);
+            }
+        }
+    }
+}
+
+
+
+static void
+doCurlWork(xmlrpc_env *       const envP,
+           struct curlMulti * const curlMultiP,
+           bool *             const rpcStillRunningP) {
+/*----------------------------------------------------------------------------
+   Do whatever work is ready to be done by the Curl multi manager
+   identified by 'curlMultiP'.  This typically is transferring data on
+   an HTTP connection because the server is ready.
+
+   Return *rpcStillRunningP false if this work completes all of the
+   manager's transactions so that there is no reason to call us ever
+   again.
+
+   Where the multi manager completes an HTTP transaction, also complete
+   the associated RPC.
+-----------------------------------------------------------------------------*/
+    bool immediateWorkToDo;
+    int runningHandles;
+
+    immediateWorkToDo = true;  /* initial assumption */
+
+    while (immediateWorkToDo && !envP->fault_occurred) {
+        curlMulti_perform(envP, curlMultiP,
+                          &immediateWorkToDo, &runningHandles);
+    }
+
+    /* We either did all the work that's ready to do or hit an error. */
+
+    if (!envP->fault_occurred) {
+        /* The work we did may have resulted in asynchronous messages
+           (asynchronous to the thing the refer to, not to us, of course).
+           In particular the message "Curl transaction has completed".
+           So we process those now.
+        */
+        processCurlMessages(envP, curlMultiP);
+
+        *rpcStillRunningP = runningHandles > 0;
+    }
+}
+
+
+
+static void
+finishCurlSessions(xmlrpc_env *       const envP,
+                   struct curlMulti * const curlMultiP,
+                   xmlrpc_timeoutType const timeoutType,
+                   struct timeval     const deadline) {
+
+    bool rpcStillRunning;
+    bool timedOut;
+    
+    rpcStillRunning = true;  /* initial assumption */
+    timedOut = false;
+    
+    while (rpcStillRunning && !timedOut && !envP->fault_occurred) {
+        waitForWork(envP, curlMultiP, timeoutType, deadline);
+
+        if (!envP->fault_occurred) {
+            struct timeval nowTime;
+
+            doCurlWork(envP, curlMultiP, &rpcStillRunning);
+            
+            gettimeofday(&nowTime, NULL);
+            
+            timedOut = (timeoutType == timeout_yes &&
+                        timeIsAfter(nowTime, deadline));
+        }
+    }
+}
+
+
+
+static void 
+finishAsynch(
+    struct xmlrpc_client_transport * const clientTransportP,
+    xmlrpc_timeoutType               const timeoutType,
+    xmlrpc_timeout                   const timeout) {
+/*----------------------------------------------------------------------------
+   Wait for the Curl multi manager to finish the Curl transactions for
+   all outstanding RPCs and destroy those RPCs.
+
+   This does the 'finish_asynch' operation for a Curl client transport.
+
+   It would be cool to replace this with something analogous to the
+   Curl asynchronous interface: Have something like curl_multi_fdset()
+   that returns a bunch of file descriptors on which the user can wait
+   (along with possibly other file descriptors of his own) and
+   something like curl_multi_perform() to finish whatever RPCs are
+   ready to finish at that moment.  The implementation would be little
+   more than wrapping curl_multi_fdset() and curl_multi_perform().
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+
+    struct timeval waitTimeoutTime;
+        /* The datetime after which we should quit waiting */
+
+    xmlrpc_env_init(&env);
+    
+    if (timeoutType == timeout_yes) {
+        struct timeval waitStartTime;
+        gettimeofday(&waitStartTime, NULL);
+        addMilliseconds(waitStartTime, timeout, &waitTimeoutTime);
+    }
+
+    finishCurlSessions(&env, clientTransportP->curlMultiP,
+                       timeoutType, waitTimeoutTime);
+
+    /* If the above fails, it is catastrophic, because it means there is
+       no way to complete outstanding Curl transactions and RPCs, and
+       no way to release their resources.
+
+       We should at least expand this interface some day to push the
+       problem back up the user, but for now we just do this Hail Mary
+       response.
+
+       Note that a failure of finishCurlSessions() does not mean that
+       a session completed with an error or an RPC completed with an
+       error.  Those things are reported up through the user's 
+       xmlrpc_transport_asynch_complete routine.  A failure here is
+       something that stopped us from calling that.
+    */
+
+    if (env.fault_occurred)
+        fprintf(stderr, "finishAsync() failed.  Xmlrpc-c Curl transport "
+                "is now in an unknown state and may not be able to "
+                "continue functioning.  Specifics of the failure: %s\n",
+                env.fault_string);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+call(xmlrpc_env *                     const envP,
+     struct xmlrpc_client_transport * const clientTransportP,
+     const xmlrpc_server_info *       const serverP,
+     xmlrpc_mem_block *               const callXmlP,
+     xmlrpc_mem_block **              const responseXmlPP) {
+
+    xmlrpc_mem_block * responseXmlP;
+    rpc * rpcP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(serverP);
+    XMLRPC_ASSERT_PTR_OK(callXmlP);
+    XMLRPC_ASSERT_PTR_OK(responseXmlPP);
+
+    responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+    if (!envP->fault_occurred) {
+        /* Only one RPC at a time can use a Curl session, so we have to
+           hold the lock as long as our RPC exists.
+        */
+        lockSyncCurlSession(clientTransportP);
+        createRpc(envP, clientTransportP, clientTransportP->syncCurlSessionP,
+                  serverP,
+                  callXmlP, responseXmlP,
+                  NULL, NULL,
+                  &rpcP);
+
+        if (!envP->fault_occurred) {
+            performRpc(envP, rpcP);
+
+            *responseXmlPP = responseXmlP;
+
+            destroyRpc(rpcP);
+        }
+        unlockSyncCurlSession(clientTransportP);
+        if (envP->fault_occurred)
+            XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
+    }
+}
+
+
+
+static void
+setupGlobalConstants(xmlrpc_env * const envP) {
+/*----------------------------------------------------------------------------
+   See longwinded discussion of the global constant issue at the top of
+   this file.
+-----------------------------------------------------------------------------*/
+    initWindowsStuff(envP);
+
+    if (!envP->fault_occurred) {
+        CURLcode rc;
+
+        rc = curl_global_init(CURL_GLOBAL_ALL);
+        
+        if (rc != CURLE_OK)
+            xmlrpc_faultf(envP, "curl_global_init() failed with code %d", rc);
+    }
+}
+
+
+
+static void
+teardownGlobalConstants(void) {
+/*----------------------------------------------------------------------------
+   See longwinded discussionof the global constant issue at the top of
+   this file.
+-----------------------------------------------------------------------------*/
+    curl_global_cleanup();
+
+    termWindowsStuff();
+}
+
+
+
+struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops = {
+    &setupGlobalConstants,
+    &teardownGlobalConstants,
+    &create,
+    &destroy,
+    &sendRequest,
+    &call,
+    &finishAsynch,
+};
diff --git a/lib/curl_transport/xmlrpc_curl_transport.h b/lib/curl_transport/xmlrpc_curl_transport.h
new file mode 100644 (file)
index 0000000..1425add
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef XMLRPC_CURL_TRANSPORT_H
+#define XMLRPC_CURL_TRANSPORT_H
+
+#include "xmlrpc-c/transport.h"
+
+extern struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops;
+
+#endif
diff --git a/lib/expat/Makefile b/lib/expat/Makefile
new file mode 100644 (file)
index 0000000..7a85187
--- /dev/null
@@ -0,0 +1,36 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+SUBDIR = lib/expat
+
+include $(SRCDIR)/Makefile.config
+
+# Build up SUBDIRS:
+SUBDIRS = gennmtab xmlparse xmltok
+
+default: all
+
+.PHONY: all clean distclean tags distdir intall check dep
+
+all: $(SUBDIRS:%=%/all)
+
+clean: $(SUBDIRS:%=%/clean) clean-common
+
+distclean: $(SUBDIRS:%=%/distclean) distclean-common
+
+tags: $(SUBDIRS:%=%/tags) TAGS
+
+DISTFILES = 
+
+distdir: distdir-common
+
+install: $(SUBDIRS:%=%/install)
+
+check:
+
+dep: $(SUBDIRS:%=%/dep)
+
+include $(SRCDIR)/Makefile.common
+
+
+
diff --git a/lib/expat/Makefile.depend b/lib/expat/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/expat/expat.dsw b/lib/expat/expat.dsw
new file mode 100644 (file)
index 0000000..b57c9a8
--- /dev/null
@@ -0,0 +1,75 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "gennmtab"=".\gennmtab\gennmtab.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Project: "xmlparse"=".\xmlparse\xmlparse.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+    Begin Project Dependency\r
+    Project_Dep_Name xmltok\r
+    End Project Dependency\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Project: "xmltok"=".\xmltok\xmltok.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+    Begin Project Dependency\r
+    Project_Dep_Name gennmtab\r
+    End Project Dependency\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Project: "xmlwf"=".\xmlwf\xmlwf.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+    Begin Project Dependency\r
+    Project_Dep_Name xmlparse\r
+    Project_Dep_Name xmltok\r
+    End Project Dependency\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/lib/expat/expat.html b/lib/expat/expat.html
new file mode 100644 (file)
index 0000000..22216b6
--- /dev/null
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+"http://www.w3.org/TR/REC-html40/loose.dtd">
+
+<HTML>
+
+<TITLE>expat</TITLE>
+
+<BODY>
+
+<H1>expat - XML Parser Toolkit</H1>
+
+<H3>Version 1.2</H3>
+
+<P>Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center
+Ltd.  Expat is freely available with source under a very liberal <a
+href="copying.txt">license</a> (the MIT license).</P>
+
+<P>This is a production version of expat.  Relative to expat 1.1, it
+adds support for parsing external DTDs and parameter entities.
+Compiling with -DXML_DTD enables this support.  There's a new
+<CODE>-p</CODE> option for xmlwf which will cause it to process
+external DTDs and parameter entities; this implies the <CODE>-x</CODE>
+option.  See the comment above <CODE>XML_SetParamEntityParsing</CODE>
+in <CODE>xmlparse.h</CODE> for the API addition that enables this.</P>
+
+<P>Expat is an <A
+HREF="http://www.w3.org/TR/1998/REC-xml-19980210">XML 1.0</A> parser
+written in C. It aims to be fully conforming.  It is currently not a
+validating XML processor.  The current production version of expat 1.X
+can be downloaded from <A href =
+"ftp://ftp.jclark.com/pub/xml/expat.zip"
+>ftp://ftp.jclark.com/pub/xml/expat.zip</A>.</P>
+
+<P>Development of expat 2.0 is being handled by a team led by Clark
+Cooper, hosted by <A
+href="http://www.sourceforge.net">sourceforge.net</A>.  See <A href=
+"http://expat.sourceforge.net">http://expat.sourceforge.net</A> for
+the latest on expat 2.0.</P>
+
+<P>The directory <SAMP>xmltok</SAMP> contains a low-level library for
+tokenizing XML.  The interface is documented in
+<SAMP>xmltok/xmltok.h</SAMP>.</P>
+
+<P>The directory <SAMP>xmlparse</SAMP> contains an XML parser library
+which is built on top of the <SAMP>xmltok</SAMP> library.  The
+interface is documented in <SAMP>xmlparse/xmlparse.h</SAMP>.  The
+directory <SAMP>sample</SAMP> contains a simple example program using
+this interface; <SAMP>sample/build.bat</SAMP> is a batch file to build
+the example using Visual C++.</P>
+
+<P>The directory <SAMP>xmlwf</SAMP> contains the <SAMP>xmlwf</SAMP>
+application, which uses the <SAMP>xmlparse</SAMP> library. The
+arguments to <SAMP>xmlwf</SAMP> are one or more files which are each
+to be checked for well-formedness. An option <SAMP>-d
+<VAR>dir</VAR></SAMP> can be specified; for each well-formed input
+file the corresponding <A
+href="http://www.jclark.com/xml/canonxml.html">canonical XML</A> will
+be written to <SAMP>dir/<VAR>f</VAR></SAMP>, where
+<SAMP><VAR>f</VAR></SAMP> is the filename (without any path) of the
+input file.  A <CODE>-x</CODE> option will cause references to
+external general entities to be processed.  A <CODE>-s</CODE> option
+will make documents that are not standalone cause an error (a document
+is considered standalone if either it is intrinsically standalone
+because it has no external subset and no references to parameter
+entities in the internal subset or it is declared as standalone in the
+XML declaration).</P>
+
+<P>The <SAMP>bin</SAMP> directory contains Win32 executables.  The
+<SAMP>lib</SAMP> directory contains Win32 import libraries.</P>
+
+<P>Answers to some frequently asked questions about expat can be found
+in the <A
+HREF="http://www.jclark.com/xml/expatfaq.html">expat
+FAQ</A>.</P>
+
+<P></P>
+
+<ADDRESS>
+
+<A HREF="mailto:jjc@jclark.com">James Clark</A>
+
+</ADDRESS>
+
+</BODY>
+
+</HTML>
diff --git a/lib/expat/gennmtab/.cvsignore b/lib/expat/gennmtab/.cvsignore
new file mode 100644 (file)
index 0000000..b1f2027
--- /dev/null
@@ -0,0 +1 @@
+gennmtab
diff --git a/lib/expat/gennmtab/Makefile b/lib/expat/gennmtab/Makefile
new file mode 100644 (file)
index 0000000..03891e9
--- /dev/null
@@ -0,0 +1,45 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../../..
+endif
+
+include $(SRCDIR)/Makefile.config
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+LDFLAGS = $(LADD)
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/lib/util/include
+
+default: all
+
+include $(SRCDIR)/Makefile.common
+
+.PHONY: all
+all: gennmtab
+
+.PHONY: clean
+clean: clean-common
+       rm -f gennmtab
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: tags
+tags: TAGS
+
+.PHONY: distdir
+distdir:
+
+.PHONY: install
+install:
+
+.PHONY: dep
+dep: dep-common
+
+gennmtab.o:%.o:%.c
+       $(BUILDTOOL_CC) -c $< -o $@ $(CFLAGS) $(INCLUDES)
+
+gennmtab:%:%.o
+       $(BUILDTOOL_CCLD) -o $@ $(LDFLAGS) $^
+
+include Makefile.depend
diff --git a/lib/expat/gennmtab/Makefile.depend b/lib/expat/gennmtab/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/expat/gennmtab/gennmtab.c b/lib/expat/gennmtab/gennmtab.c
new file mode 100644 (file)
index 0000000..c6bdb7d
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#include "xmlrpc_config.h"
+
+struct range {
+  int start;
+  int end;
+};
+
+struct range nmstrt[] = {
+  { '_',    0 },
+  { ':',    0 },
+  /* BaseChar */
+  { 0x0041, 0x005a },
+  { 0x0061, 0x007a },
+  { 0x00c0, 0x00d6 },
+  { 0x00d8, 0x00f6 },
+  { 0x00f8, 0x00ff },
+  { 0x0100, 0x0131 },
+  { 0x0134, 0x013e },
+  { 0x0141, 0x0148 },
+  { 0x014a, 0x017e },
+  { 0x0180, 0x01c3 },
+  { 0x01cd, 0x01f0 },
+  { 0x01f4, 0x01f5 },
+  { 0x01fa, 0x0217 },
+  { 0x0250, 0x02a8 },
+  { 0x02bb, 0x02c1 },
+  { 0x0386, 0      },
+  { 0x0388, 0x038a },
+  { 0x038c, 0      },
+  { 0x038e, 0x03a1 },
+  { 0x03a3, 0x03ce },
+  { 0x03d0, 0x03d6 },
+  { 0x03da, 0      },
+  { 0x03dc, 0      },
+  { 0x03de, 0      },
+  { 0x03e0, 0      },
+  { 0x03e2, 0x03f3 },
+  { 0x0401, 0x040c },
+  { 0x040e, 0x044f },
+  { 0x0451, 0x045c },
+  { 0x045e, 0x0481 },
+  { 0x0490, 0x04c4 },
+  { 0x04c7, 0x04c8 },
+  { 0x04cb, 0x04cc },
+  { 0x04d0, 0x04eb },
+  { 0x04ee, 0x04f5 },
+  { 0x04f8, 0x04f9 },
+  { 0x0531, 0x0556 },
+  { 0x0559, 0      },
+  { 0x0561, 0x0586 },
+  { 0x05d0, 0x05ea },
+  { 0x05f0, 0x05f2 },
+  { 0x0621, 0x063a },
+  { 0x0641, 0x064a },
+  { 0x0671, 0x06b7 },
+  { 0x06ba, 0x06be },
+  { 0x06c0, 0x06ce },
+  { 0x06d0, 0x06d3 },
+  { 0x06d5, 0      },
+  { 0x06e5, 0x06e6 },
+  { 0x0905, 0x0939 },
+  { 0x093d, 0      },
+  { 0x0958, 0x0961 },
+  { 0x0985, 0x098c },
+  { 0x098f, 0x0990 },
+  { 0x0993, 0x09a8 },
+  { 0x09aa, 0x09b0 },
+  { 0x09b2, 0      },
+  { 0x09b6, 0x09b9 },
+  { 0x09dc, 0x09dd },
+  { 0x09df, 0x09e1 },
+  { 0x09f0, 0x09f1 },
+  { 0x0a05, 0x0a0a },
+  { 0x0a0f, 0x0a10 },
+  { 0x0a13, 0x0a28 },
+  { 0x0a2a, 0x0a30 },
+  { 0x0a32, 0x0a33 },
+  { 0x0a35, 0x0a36 },
+  { 0x0a38, 0x0a39 },
+  { 0x0a59, 0x0a5c },
+  { 0x0a5e, 0      },
+  { 0x0a72, 0x0a74 },
+  { 0x0a85, 0x0a8b },
+  { 0x0a8d, 0      },
+  { 0x0a8f, 0x0a91 },
+  { 0x0a93, 0x0aa8 },
+  { 0x0aaa, 0x0ab0 },
+  { 0x0ab2, 0x0ab3 },
+  { 0x0ab5, 0x0ab9 },
+  { 0x0abd, 0      },
+  { 0x0ae0, 0      },
+  { 0x0b05, 0x0b0c },
+  { 0x0b0f, 0x0b10 },
+  { 0x0b13, 0x0b28 },
+  { 0x0b2a, 0x0b30 },
+  { 0x0b32, 0x0b33 },
+  { 0x0b36, 0x0b39 },
+  { 0x0b3d, 0      },
+  { 0x0b5c, 0x0b5d },
+  { 0x0b5f, 0x0b61 },
+  { 0x0b85, 0x0b8a },
+  { 0x0b8e, 0x0b90 },
+  { 0x0b92, 0x0b95 },
+  { 0x0b99, 0x0b9a },
+  { 0x0b9c, 0      },
+  { 0x0b9e, 0x0b9f },
+  { 0x0ba3, 0x0ba4 },
+  { 0x0ba8, 0x0baa },
+  { 0x0bae, 0x0bb5 },
+  { 0x0bb7, 0x0bb9 },
+  { 0x0c05, 0x0c0c },
+  { 0x0c0e, 0x0c10 },
+  { 0x0c12, 0x0c28 },
+  { 0x0c2a, 0x0c33 },
+  { 0x0c35, 0x0c39 },
+  { 0x0c60, 0x0c61 },
+  { 0x0c85, 0x0c8c },
+  { 0x0c8e, 0x0c90 },
+  { 0x0c92, 0x0ca8 },
+  { 0x0caa, 0x0cb3 },
+  { 0x0cb5, 0x0cb9 },
+  { 0x0cde, 0      },
+  { 0x0ce0, 0x0ce1 },
+  { 0x0d05, 0x0d0c },
+  { 0x0d0e, 0x0d10 },
+  { 0x0d12, 0x0d28 },
+  { 0x0d2a, 0x0d39 },
+  { 0x0d60, 0x0d61 },
+  { 0x0e01, 0x0e2e },
+  { 0x0e30, 0      },
+  { 0x0e32, 0x0e33 },
+  { 0x0e40, 0x0e45 },
+  { 0x0e81, 0x0e82 },
+  { 0x0e84, 0      },
+  { 0x0e87, 0x0e88 },
+  { 0x0e8a, 0      },
+  { 0x0e8d, 0      },
+  { 0x0e94, 0x0e97 },
+  { 0x0e99, 0x0e9f },
+  { 0x0ea1, 0x0ea3 },
+  { 0x0ea5, 0      },
+  { 0x0ea7, 0      },
+  { 0x0eaa, 0x0eab },
+  { 0x0ead, 0x0eae },
+  { 0x0eb0, 0      },
+  { 0x0eb2, 0x0eb3 },
+  { 0x0ebd, 0      },
+  { 0x0ec0, 0x0ec4 },
+  { 0x0f40, 0x0f47 },
+  { 0x0f49, 0x0f69 },
+  { 0x10a0, 0x10c5 },
+  { 0x10d0, 0x10f6 },
+  { 0x1100, 0      },
+  { 0x1102, 0x1103 },
+  { 0x1105, 0x1107 },
+  { 0x1109, 0      },
+  { 0x110b, 0x110c },
+  { 0x110e, 0x1112 },
+  { 0x113c, 0      },
+  { 0x113e, 0      },
+  { 0x1140, 0      },
+  { 0x114c, 0      },
+  { 0x114e, 0      },
+  { 0x1150, 0      },
+  { 0x1154, 0x1155 },
+  { 0x1159, 0      },
+  { 0x115f, 0x1161 },
+  { 0x1163, 0      },
+  { 0x1165, 0      },
+  { 0x1167, 0      },
+  { 0x1169, 0      },
+  { 0x116d, 0x116e },
+  { 0x1172, 0x1173 },
+  { 0x1175, 0      },
+  { 0x119e, 0      },
+  { 0x11a8, 0      },
+  { 0x11ab, 0      },
+  { 0x11ae, 0x11af },
+  { 0x11b7, 0x11b8 },
+  { 0x11ba, 0      },
+  { 0x11bc, 0x11c2 },
+  { 0x11eb, 0      },
+  { 0x11f0, 0      },
+  { 0x11f9, 0      },
+  { 0x1e00, 0x1e9b },
+  { 0x1ea0, 0x1ef9 },
+  { 0x1f00, 0x1f15 },
+  { 0x1f18, 0x1f1d },
+  { 0x1f20, 0x1f45 },
+  { 0x1f48, 0x1f4d },
+  { 0x1f50, 0x1f57 },
+  { 0x1f59, 0      },
+  { 0x1f5b, 0      },
+  { 0x1f5d, 0      },
+  { 0x1f5f, 0x1f7d },
+  { 0x1f80, 0x1fb4 },
+  { 0x1fb6, 0x1fbc },
+  { 0x1fbe, 0      },
+  { 0x1fc2, 0x1fc4 },
+  { 0x1fc6, 0x1fcc },
+  { 0x1fd0, 0x1fd3 },
+  { 0x1fd6, 0x1fdb },
+  { 0x1fe0, 0x1fec },
+  { 0x1ff2, 0x1ff4 },
+  { 0x1ff6, 0x1ffc },
+  { 0x2126, 0      },
+  { 0x212a, 0x212b },
+  { 0x212e, 0      },
+  { 0x2180, 0x2182 },
+  { 0x3041, 0x3094 },
+  { 0x30a1, 0x30fa },
+  { 0x3105, 0x312c },
+  { 0xac00, 0xd7a3 },
+  /* Ideographic */
+  { 0x4e00, 0x9fa5 },
+  { 0x3007, 0      },
+  { 0x3021, 0x3029 },
+};
+
+/* name chars that are not name start chars */
+struct range name[] = {
+  { '.', 0 },
+  { '-', 0 },
+  /* CombiningChar */
+  { 0x0300, 0x0345 },
+  { 0x0360, 0x0361 },
+  { 0x0483, 0x0486 },
+  { 0x0591, 0x05a1 },
+  { 0x05a3, 0x05b9 },
+  { 0x05bb, 0x05bd },
+  { 0x05bf, 0      },
+  { 0x05c1, 0x05c2 },
+  { 0x05c4, 0      },
+  { 0x064b, 0x0652 },
+  { 0x0670, 0      },
+  { 0x06d6, 0x06dc },
+  { 0x06dd, 0x06df },
+  { 0x06e0, 0x06e4 },
+  { 0x06e7, 0x06e8 },
+  { 0x06ea, 0x06ed },
+  { 0x0901, 0x0903 },
+  { 0x093c, 0      },
+  { 0x093e, 0x094c },
+  { 0x094d, 0      },
+  { 0x0951, 0x0954 },
+  { 0x0962, 0x0963 },
+  { 0x0981, 0x0983 },
+  { 0x09bc, 0      },
+  { 0x09be, 0      },
+  { 0x09bf, 0      },
+  { 0x09c0, 0x09c4 },
+  { 0x09c7, 0x09c8 },
+  { 0x09cb, 0x09cd },
+  { 0x09d7, 0      },
+  { 0x09e2, 0x09e3 },
+  { 0x0a02, 0      },
+  { 0x0a3c, 0      },
+  { 0x0a3e, 0      },
+  { 0x0a3f, 0      },
+  { 0x0a40, 0x0a42 },
+  { 0x0a47, 0x0a48 },
+  { 0x0a4b, 0x0a4d },
+  { 0x0a70, 0x0a71 },
+  { 0x0a81, 0x0a83 },
+  { 0x0abc, 0      },
+  { 0x0abe, 0x0ac5 },
+  { 0x0ac7, 0x0ac9 },
+  { 0x0acb, 0x0acd },
+  { 0x0b01, 0x0b03 },
+  { 0x0b3c, 0      },
+  { 0x0b3e, 0x0b43 },
+  { 0x0b47, 0x0b48 },
+  { 0x0b4b, 0x0b4d },
+  { 0x0b56, 0x0b57 },
+  { 0x0b82, 0x0b83 },
+  { 0x0bbe, 0x0bc2 },
+  { 0x0bc6, 0x0bc8 },
+  { 0x0bca, 0x0bcd },
+  { 0x0bd7, 0      },
+  { 0x0c01, 0x0c03 },
+  { 0x0c3e, 0x0c44 },
+  { 0x0c46, 0x0c48 },
+  { 0x0c4a, 0x0c4d },
+  { 0x0c55, 0x0c56 },
+  { 0x0c82, 0x0c83 },
+  { 0x0cbe, 0x0cc4 },
+  { 0x0cc6, 0x0cc8 },
+  { 0x0cca, 0x0ccd },
+  { 0x0cd5, 0x0cd6 },
+  { 0x0d02, 0x0d03 },
+  { 0x0d3e, 0x0d43 },
+  { 0x0d46, 0x0d48 },
+  { 0x0d4a, 0x0d4d },
+  { 0x0d57, 0      },
+  { 0x0e31, 0      },
+  { 0x0e34, 0x0e3a },
+  { 0x0e47, 0x0e4e },
+  { 0x0eb1, 0      },
+  { 0x0eb4, 0x0eb9 },
+  { 0x0ebb, 0x0ebc },
+  { 0x0ec8, 0x0ecd },
+  { 0x0f18, 0x0f19 },
+  { 0x0f35, 0      },
+  { 0x0f37, 0      },
+  { 0x0f39, 0      },
+  { 0x0f3e, 0      },
+  { 0x0f3f, 0      },
+  { 0x0f71, 0x0f84 },
+  { 0x0f86, 0x0f8b },
+  { 0x0f90, 0x0f95 },
+  { 0x0f97, 0      },
+  { 0x0f99, 0x0fad },
+  { 0x0fb1, 0x0fb7 },
+  { 0x0fb9, 0      },
+  { 0x20d0, 0x20dc },
+  { 0x20e1, 0      },
+  { 0x302a, 0x302f },
+  { 0x3099, 0      },
+  { 0x309a, 0      },
+  /* Digit */
+  { 0x0030, 0x0039 },
+  { 0x0660, 0x0669 },
+  { 0x06f0, 0x06f9 },
+  { 0x0966, 0x096f },
+  { 0x09e6, 0x09ef },
+  { 0x0a66, 0x0a6f },
+  { 0x0ae6, 0x0aef },
+  { 0x0b66, 0x0b6f },
+  { 0x0be7, 0x0bef },
+  { 0x0c66, 0x0c6f },
+  { 0x0ce6, 0x0cef },
+  { 0x0d66, 0x0d6f },
+  { 0x0e50, 0x0e59 },
+  { 0x0ed0, 0x0ed9 },
+  { 0x0f20, 0x0f29 },
+  /* Extender */
+  { 0xb7  , 0      },
+  { 0x02d0, 0      },
+  { 0x02d1, 0      },
+  { 0x0387, 0      },
+  { 0x0640, 0      },
+  { 0x0e46, 0      },
+  { 0x0ec6, 0      },
+  { 0x3005, 0      },
+  { 0x3031, 0x3035 },
+  { 0x309d, 0x309e },
+  { 0x30fc, 0x30fe },
+};
+
+static void 
+setTab(char *tab, struct range *ranges, size_t nRanges)
+{
+  size_t i;
+  int j;
+  for (i = 0; i < nRanges; i++) {
+    if (ranges[i].end) {
+      for (j = ranges[i].start; j <= ranges[i].end; j++)
+       tab[j] = 1;
+    }
+    else
+      tab[ranges[i].start] = 1;
+  }
+}
+
+static void 
+printTabs(char *tab)
+{ 
+  int nBitmaps = 2;
+  int i, j, k;
+  unsigned char pageIndex[512];
+
+  printf(
+"static const unsigned namingBitmap[] = {\n\
+0x00000000, 0x00000000, 0x00000000, 0x00000000,\n\
+0x00000000, 0x00000000, 0x00000000, 0x00000000,\n\
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,\n\
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,\n");
+  for (i = 0; i < 512; i++) {
+    int kind = tab[i*256];
+    for (j = 1; j < 256; j++)
+      if (tab[i*256 +j] != kind) {
+       kind = -1;
+       break;
+      }
+    if (i >= 256 &&  memcmp(tab + (i - 256)*256, tab + i*256, 256) == 0)
+      pageIndex[i] = pageIndex[i - 256];
+    else if (kind == -1) { 
+      pageIndex[i] = nBitmaps++;
+      for (j = 0; j < 8; j++) {
+       unsigned val = 0;
+       for (k = 0; k < 32; k++) {
+         if (tab[i*256 + j*32 +k])
+           val |= (1 << k);
+       }
+       printf("0x%08X,", val);
+       putchar((((j + 1) & 3) == 0) ? '\n' : ' ');
+      }
+    }
+    else
+      pageIndex[i] = kind;
+  }
+  printf("};\n");
+  printf("static const unsigned char nmstrtPages[] = {\n");
+  for (i = 0; i < 512; i++) {
+    if (i == 256)
+      printf("};\nstatic const unsigned char namePages[] = {\n");
+    printf("0x%02X,", pageIndex[i]);
+    putchar((((i + 1) & 7) == 0) ? '\n' : ' ');
+  }
+  printf("};\n");
+}
+
+int 
+main(int     const argc ATTR_UNUSED,
+     char ** const argv ATTR_UNUSED) { 
+
+  char tab[2*65536];
+  memset(tab, 0, 65536);
+  setTab(tab, nmstrt, sizeof(nmstrt)/sizeof(nmstrt[0]));
+  memcpy(tab + 65536, tab, 65536);
+  setTab(tab + 65536, name, sizeof(name)/sizeof(name[0]));
+  printTabs(tab);
+  return 0;
+}
diff --git a/lib/expat/gennmtab/gennmtab.dsp b/lib/expat/gennmtab/gennmtab.dsp
new file mode 100644 (file)
index 0000000..917dc44
--- /dev/null
@@ -0,0 +1,110 @@
+# Microsoft Developer Studio Project File - Name="gennmtab" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gennmtab - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "gennmtab.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "gennmtab.mak" CFG="gennmtab - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "gennmtab - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gennmtab - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "gennmtab"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "gennmtab - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\gennmtab"
+# PROP Intermediate_Dir "Release\gennmtab"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\..\..\Bin\gennmtab.exe"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=..\..\..\Bin\gennmtab.exe >..\xmltok\nametab.h
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "gennmtab - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\gennmtab"
+# PROP Intermediate_Dir "Debug\gennmtab"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\Bin\gennmtabD.exe"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=..\..\..\Bin\gennmtabD.exe >..\xmltok\nametab.h
+# End Special Build Tool
+
+!ENDIF 
+
+# Begin Target
+
+# Name "gennmtab - Win32 Release"
+# Name "gennmtab - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\gennmtab.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/lib/expat/xmlparse/Makefile b/lib/expat/xmlparse/Makefile
new file mode 100644 (file)
index 0000000..96c0be8
--- /dev/null
@@ -0,0 +1,57 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../../..
+endif
+SUBDIR = lib/expat/xmlparse
+# BLDDIR is for use in places where a symbolic link won't work.
+# BUILDDIR is for places in Makefile.common that can use the 'blddir'
+# symbolic link (but in other directories, doesn't).
+BLDDIR = ../../..
+BUILDDIR = blddir
+VPATH = .:$(SRCDIR)
+
+XMLTOKDIR = ../xmltok
+UTILDIR = $(SRCDIR)/lib/util
+
+include $(BLDDIR)/Makefile.config
+
+default: all
+
+all: libxmlrpc_xmlparse.la
+
+LIBXMLRPC_XMLPARSE_OBJS = xmlparse.lo
+
+INCLUDES = -Iblddir -I$(SRCDIR) -I$(UTILDIR)/include -I$(XMLTOKDIR)
+
+LDFLAGS = $(LADD)
+
+LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR) $(LADD)
+
+libxmlrpc_xmlparse.la: $(LIBXMLRPC_XMLPARSE_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+$(LIBXMLRPC_XMLPARSE_OBJS):%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+LTLIBRARIES_TO_INSTALL = libxmlrpc_xmlparse.la
+
+.PHONY: install
+install: install-common
+
+.PHONY: clean distclean
+clean: clean-common
+
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
+
+# This 'Makefile.common' dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/Makefile.common: srcdir blddir
+
+include $(SRCDIR)/Makefile.common
+
+include Makefile.depend
diff --git a/lib/expat/xmlparse/Makefile.depend b/lib/expat/xmlparse/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/expat/xmlparse/xmlparse.c b/lib/expat/xmlparse/xmlparse.c
new file mode 100644 (file)
index 0000000..abe9874
--- /dev/null
@@ -0,0 +1,4057 @@
+/*
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+/* In 2001, this was part of the Expat package.  We copied it into
+   Xmlrpc-c because it's easier on the user than making him get and
+   link Expat separately, and we don't expect to benefit from separate
+   maintenance of Expat.
+
+   But we changed all the external symbols that in Expat are named
+   "XML_xxxx" to "xmlrpc_XML_xxxx" because people do link Xmlrpc-c
+   libraries into programs that also link Expat (a good example is
+   where an Apache module uses Xmlrpc-c).  We don't want our names to
+   collide with Expat's.
+*/
+
+#include <stddef.h>
+
+#include "xmlrpc_config.h"
+#include "c_util.h"
+#include "xmldef.h"
+#include "xmlparse.h"
+
+#ifdef XML_UNICODE
+#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
+#define XmlConvert XmlUtf16Convert
+#define XmlGetInternalEncoding xmlrpc_XmlGetUtf16InternalEncoding
+#define XmlGetInternalEncodingNS xmlrpc_XmlGetUtf16InternalEncodingNS
+#define XmlEncode xmlrpc_XmlUtf16Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
+typedef unsigned short ICHAR;
+#else
+#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
+#define XmlConvert XmlUtf8Convert
+#define XmlGetInternalEncoding xmlrpc_XmlGetUtf8InternalEncoding
+#define XmlGetInternalEncodingNS xmlrpc_XmlGetUtf8InternalEncodingNS
+#define XmlEncode xmlrpc_XmlUtf8Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
+typedef char ICHAR;
+#endif
+
+
+#ifndef XML_NS
+
+#define XmlInitEncodingNS xmlrpc_XmlInitEncoding
+#define XmlInitUnknownEncodingNS xmlrpc_XmlInitUnknownEncoding
+#undef XmlGetInternalEncodingNS
+#define XmlGetInternalEncodingNS XmlGetInternalEncoding
+#define XmlParseXmlDeclNS xmlrpc_XmlParseXmlDecl
+
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_T(x) L ## x
+#else
+#define XML_T(x) x
+#endif
+
+/* Round up n to be a multiple of sz, where sz is a power of 2. */
+#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
+
+#include "xmltok.h"
+#include "xmlrole.h"
+
+typedef const XML_Char *KEY;
+
+typedef struct {
+  KEY name;
+} NAMED;
+
+typedef struct {
+  NAMED **v;
+  size_t size;
+  size_t used;
+  size_t usedLim;
+} HASH_TABLE;
+
+typedef struct {
+  NAMED **p;
+  NAMED **end;
+} HASH_TABLE_ITER;
+
+#define INIT_TAG_BUF_SIZE 32  /* must be a multiple of sizeof(XML_Char) */
+#define INIT_DATA_BUF_SIZE 1024
+#define INIT_ATTS_SIZE 16
+#define INIT_BLOCK_SIZE 1024
+#define INIT_BUFFER_SIZE 1024
+
+#define EXPAND_SPARE 24
+
+typedef struct binding {
+  struct prefix *prefix;
+  struct binding *nextTagBinding;
+  struct binding *prevPrefixBinding;
+  const struct attribute_id *attId;
+  XML_Char *uri;
+  int uriLen;
+  int uriAlloc;
+} BINDING;
+
+typedef struct prefix {
+  const XML_Char *name;
+  BINDING *binding;
+} PREFIX;
+
+typedef struct {
+  const XML_Char *str;
+  const XML_Char *localPart;
+  int uriLen;
+} TAG_NAME;
+
+typedef struct tag {
+  struct tag *parent;
+  const char *rawName;
+  int rawNameLength;
+  TAG_NAME name;
+  char *buf;
+  char *bufEnd;
+  BINDING *bindings;
+} TAG;
+
+typedef struct {
+  const XML_Char *name;
+  const XML_Char *textPtr;
+  int textLen;
+  const XML_Char *systemId;
+  const XML_Char *base;
+  const XML_Char *publicId;
+  const XML_Char *notation;
+  char open;
+} ENTITY;
+
+typedef struct block {
+  struct block *next;
+  int size;
+  XML_Char s[1];
+} BLOCK;
+
+typedef struct {
+  BLOCK *blocks;
+  BLOCK *freeBlocks;
+  const XML_Char *end;
+  XML_Char *ptr;
+  XML_Char *start;
+} STRING_POOL;
+
+/* The XML_Char before the name is used to determine whether
+an attribute has been specified. */
+typedef struct attribute_id {
+  XML_Char *name;
+  PREFIX *prefix;
+  char maybeTokenized;
+  char xmlns;
+} ATTRIBUTE_ID;
+
+typedef struct {
+  const ATTRIBUTE_ID *id;
+  char isCdata;
+  const XML_Char *value;
+} DEFAULT_ATTRIBUTE;
+
+typedef struct {
+  const XML_Char *name;
+  PREFIX *prefix;
+  const ATTRIBUTE_ID *idAtt;
+  int nDefaultAtts;
+  int allocDefaultAtts;
+  DEFAULT_ATTRIBUTE *defaultAtts;
+} ELEMENT_TYPE;
+
+typedef struct {
+  HASH_TABLE generalEntities;
+  HASH_TABLE elementTypes;
+  HASH_TABLE attributeIds;
+  HASH_TABLE prefixes;
+  STRING_POOL pool;
+  int complete;
+  int standalone;
+#ifdef XML_DTD
+  HASH_TABLE paramEntities;
+#endif /* XML_DTD */
+  PREFIX defaultPrefix;
+} DTD;
+
+typedef struct open_internal_entity {
+  const char *internalEventPtr;
+  const char *internalEventEndPtr;
+  struct open_internal_entity *next;
+  ENTITY *entity;
+} OPEN_INTERNAL_ENTITY;
+
+typedef enum XML_Error Processor(XML_Parser parser,
+                                 const char *start,
+                                 const char *end,
+                                 const char **endPtr);
+
+static Processor prologProcessor;
+static Processor prologInitProcessor;
+static Processor contentProcessor;
+static Processor cdataSectionProcessor;
+#ifdef XML_DTD
+static Processor ignoreSectionProcessor;
+#endif /* XML_DTD */
+static Processor epilogProcessor;
+static Processor errorProcessor;
+static Processor externalEntityInitProcessor;
+static Processor externalEntityInitProcessor2;
+static Processor externalEntityInitProcessor3;
+static Processor externalEntityContentProcessor;
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
+static enum XML_Error
+initializeEncoding(XML_Parser parser);
+static enum XML_Error
+doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
+         const char *end, int tok, const char *next, const char **nextPtr);
+static enum XML_Error
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+          const char *start, const char *end, const char **endPtr);
+static enum XML_Error
+doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
+#ifdef XML_DTD
+static enum XML_Error
+doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
+#endif /* XML_DTD */
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
+                                TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, int isId, const XML_Char *dfltValue);
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+                    STRING_POOL *);
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+                    STRING_POOL *);
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+static enum XML_Error
+storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+
+static const XML_Char *getContext(XML_Parser parser);
+static int setContext(XML_Parser parser, const XML_Char *context);
+static void normalizePublicId(XML_Char *s);
+static int dtdInit(DTD *);
+static void dtdDestroy(DTD *);
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd);
+static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
+#ifdef XML_DTD
+static void dtdSwap(DTD *, DTD *);
+#endif /* XML_DTD */
+static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
+static void hashTableInit(HASH_TABLE *);
+static void hashTableDestroy(HASH_TABLE *);
+static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+static NAMED *hashTableIterNext(HASH_TABLE_ITER *);
+static void poolInit(STRING_POOL *);
+static void poolClear(STRING_POOL *);
+static void poolDestroy(STRING_POOL *);
+static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+                            const char *ptr, const char *end);
+static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+                                  const char *ptr, const char *end);
+static int poolGrow(STRING_POOL *pool);
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
+
+#define poolStart(pool) ((pool)->start)
+#define poolEnd(pool) ((pool)->ptr)
+#define poolLength(pool) ((pool)->ptr - (pool)->start)
+#define poolChop(pool) ((void)--(pool->ptr))
+#define poolLastChar(pool) (((pool)->ptr)[-1])
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)
+#define poolAppendChar(pool, c) \
+  (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
+   ? 0 \
+   : ((*((pool)->ptr)++ = c), 1))
+
+typedef struct {
+  /* The first member must be userData so that the XML_GetUserData macro works. */
+  void *m_userData;
+  void *m_handlerArg;
+  char *m_buffer;
+  /* first character to be parsed */
+  const char *m_bufferPtr;
+  /* past last character to be parsed */
+  char *m_bufferEnd;
+  /* allocated end of buffer */
+  const char *m_bufferLim;
+  long m_parseEndByteIndex;
+  const char *m_parseEndPtr;
+  XML_Char *m_dataBuf;
+  XML_Char *m_dataBufEnd;
+  XML_StartElementHandler m_startElementHandler;
+  XML_EndElementHandler m_endElementHandler;
+  XML_CharacterDataHandler m_characterDataHandler;
+  XML_ProcessingInstructionHandler m_processingInstructionHandler;
+  XML_CommentHandler m_commentHandler;
+  XML_StartCdataSectionHandler m_startCdataSectionHandler;
+  XML_EndCdataSectionHandler m_endCdataSectionHandler;
+  XML_DefaultHandler m_defaultHandler;
+  XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
+  XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
+  XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
+  XML_NotationDeclHandler m_notationDeclHandler;
+  XML_ExternalParsedEntityDeclHandler m_externalParsedEntityDeclHandler;
+  XML_InternalParsedEntityDeclHandler m_internalParsedEntityDeclHandler;
+  XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
+  XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
+  XML_NotStandaloneHandler m_notStandaloneHandler;
+  XML_ExternalEntityRefHandler m_externalEntityRefHandler;
+  void *m_externalEntityRefHandlerArg;
+  XML_UnknownEncodingHandler m_unknownEncodingHandler;
+  const ENCODING *m_encoding;
+  INIT_ENCODING m_initEncoding;
+  const ENCODING *m_internalEncoding;
+  const XML_Char *m_protocolEncodingName;
+  int m_ns;
+  void *m_unknownEncodingMem;
+  void *m_unknownEncodingData;
+  void *m_unknownEncodingHandlerData;
+  void (*m_unknownEncodingRelease)(void *);
+  PROLOG_STATE m_prologState;
+  Processor *m_processor;
+  enum XML_Error m_errorCode;
+  const char *m_eventPtr;
+  const char *m_eventEndPtr;
+  const char *m_positionPtr;
+  OPEN_INTERNAL_ENTITY *m_openInternalEntities;
+  int m_defaultExpandInternalEntities;
+  int m_tagLevel;
+  ENTITY *m_declEntity;
+  const XML_Char *m_declNotationName;
+  const XML_Char *m_declNotationPublicId;
+  ELEMENT_TYPE *m_declElementType;
+  ATTRIBUTE_ID *m_declAttributeId;
+  char m_declAttributeIsCdata;
+  char m_declAttributeIsId;
+  DTD m_dtd;
+  const XML_Char *m_curBase;
+  TAG *m_tagStack;
+  TAG *m_freeTagList;
+  BINDING *m_inheritedBindings;
+  BINDING *m_freeBindingList;
+  int m_attsSize;
+  int m_nSpecifiedAtts;
+  int m_idAttIndex;
+  ATTRIBUTE *m_atts;
+  POSITION m_position;
+  STRING_POOL m_tempPool;
+  STRING_POOL m_temp2Pool;
+  char *m_groupConnector;
+  unsigned m_groupSize;
+  int m_hadExternalDoctype;
+  XML_Char m_namespaceSeparator;
+#ifdef XML_DTD
+  enum XML_ParamEntityParsing m_paramEntityParsing;
+  XML_Parser m_parentParser;
+#endif
+} Parser;
+
+#define userData (((Parser *)parser)->m_userData)
+#define handlerArg (((Parser *)parser)->m_handlerArg)
+#define startElementHandler (((Parser *)parser)->m_startElementHandler)
+#define endElementHandler (((Parser *)parser)->m_endElementHandler)
+#define characterDataHandler (((Parser *)parser)->m_characterDataHandler)
+#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler)
+#define commentHandler (((Parser *)parser)->m_commentHandler)
+#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler)
+#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler)
+#define defaultHandler (((Parser *)parser)->m_defaultHandler)
+#define startDoctypeDeclHandler (((Parser *)parser)->m_startDoctypeDeclHandler)
+#define endDoctypeDeclHandler (((Parser *)parser)->m_endDoctypeDeclHandler)
+#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler)
+#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler)
+#define externalParsedEntityDeclHandler (((Parser *)parser)->m_externalParsedEntityDeclHandler)
+#define internalParsedEntityDeclHandler (((Parser *)parser)->m_internalParsedEntityDeclHandler)
+#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler)
+#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler)
+#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler)
+#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
+#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
+#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
+#define encoding (((Parser *)parser)->m_encoding)
+#define initEncoding (((Parser *)parser)->m_initEncoding)
+#define internalEncoding (((Parser *)parser)->m_internalEncoding)
+#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
+#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData)
+#define unknownEncodingHandlerData \
+  (((Parser *)parser)->m_unknownEncodingHandlerData)
+#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease)
+#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName)
+#define ns (((Parser *)parser)->m_ns)
+#define prologState (((Parser *)parser)->m_prologState)
+#define processor (((Parser *)parser)->m_processor)
+#define errorCode (((Parser *)parser)->m_errorCode)
+#define eventPtr (((Parser *)parser)->m_eventPtr)
+#define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
+#define positionPtr (((Parser *)parser)->m_positionPtr)
+#define position (((Parser *)parser)->m_position)
+#define openInternalEntities (((Parser *)parser)->m_openInternalEntities)
+#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities)
+#define tagLevel (((Parser *)parser)->m_tagLevel)
+#define buffer (((Parser *)parser)->m_buffer)
+#define bufferPtr (((Parser *)parser)->m_bufferPtr)
+#define bufferEnd (((Parser *)parser)->m_bufferEnd)
+#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex)
+#define parseEndPtr (((Parser *)parser)->m_parseEndPtr)
+#define bufferLim (((Parser *)parser)->m_bufferLim)
+#define dataBuf (((Parser *)parser)->m_dataBuf)
+#define dataBufEnd (((Parser *)parser)->m_dataBufEnd)
+#define dtd (((Parser *)parser)->m_dtd)
+#define curBase (((Parser *)parser)->m_curBase)
+#define declEntity (((Parser *)parser)->m_declEntity)
+#define declNotationName (((Parser *)parser)->m_declNotationName)
+#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId)
+#define declElementType (((Parser *)parser)->m_declElementType)
+#define declAttributeId (((Parser *)parser)->m_declAttributeId)
+#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata)
+#define declAttributeIsId (((Parser *)parser)->m_declAttributeIsId)
+#define freeTagList (((Parser *)parser)->m_freeTagList)
+#define freeBindingList (((Parser *)parser)->m_freeBindingList)
+#define inheritedBindings (((Parser *)parser)->m_inheritedBindings)
+#define tagStack (((Parser *)parser)->m_tagStack)
+#define atts (((Parser *)parser)->m_atts)
+#define attsSize (((Parser *)parser)->m_attsSize)
+#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts)
+#define idAttIndex (((Parser *)parser)->m_idAttIndex)
+#define tempPool (((Parser *)parser)->m_tempPool)
+#define temp2Pool (((Parser *)parser)->m_temp2Pool)
+#define groupConnector (((Parser *)parser)->m_groupConnector)
+#define groupSize (((Parser *)parser)->m_groupSize)
+#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
+#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
+#ifdef XML_DTD
+#define parentParser (((Parser *)parser)->m_parentParser)
+#define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing)
+#endif /* XML_DTD */
+
+#ifdef _MSC_VER
+#ifdef _DEBUG
+Parser *asParser(XML_Parser parser)
+{
+  return parser;
+}
+#endif
+#endif
+
+XML_Parser
+xmlrpc_XML_ParserCreate(const XML_Char *encodingName)
+{
+  XML_Parser parser = malloc(sizeof(Parser));
+  if (!parser)
+    return parser;
+  processor = prologInitProcessor;
+  xmlrpc_XmlPrologStateInit(&prologState);
+  userData = 0;
+  handlerArg = 0;
+  startElementHandler = 0;
+  endElementHandler = 0;
+  characterDataHandler = 0;
+  processingInstructionHandler = 0;
+  commentHandler = 0;
+  startCdataSectionHandler = 0;
+  endCdataSectionHandler = 0;
+  defaultHandler = 0;
+  startDoctypeDeclHandler = 0;
+  endDoctypeDeclHandler = 0;
+  unparsedEntityDeclHandler = 0;
+  notationDeclHandler = 0;
+  externalParsedEntityDeclHandler = 0;
+  internalParsedEntityDeclHandler = 0;
+  startNamespaceDeclHandler = 0;
+  endNamespaceDeclHandler = 0;
+  notStandaloneHandler = 0;
+  externalEntityRefHandler = 0;
+  externalEntityRefHandlerArg = parser;
+  unknownEncodingHandler = 0;
+  buffer = 0;
+  bufferPtr = 0;
+  bufferEnd = 0;
+  parseEndByteIndex = 0;
+  parseEndPtr = 0;
+  bufferLim = 0;
+  declElementType = 0;
+  declAttributeId = 0;
+  declEntity = 0;
+  declNotationName = 0;
+  declNotationPublicId = 0;
+  memset(&position, 0, sizeof(POSITION));
+  errorCode = XML_ERROR_NONE;
+  eventPtr = 0;
+  eventEndPtr = 0;
+  positionPtr = 0;
+  openInternalEntities = 0;
+  tagLevel = 0;
+  tagStack = 0;
+  freeTagList = 0;
+  freeBindingList = 0;
+  inheritedBindings = 0;
+  attsSize = INIT_ATTS_SIZE;
+  atts = malloc(attsSize * sizeof(ATTRIBUTE));
+  nSpecifiedAtts = 0;
+  dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+  groupSize = 0;
+  groupConnector = 0;
+  hadExternalDoctype = 0;
+  unknownEncodingMem = 0;
+  unknownEncodingRelease = 0;
+  unknownEncodingData = 0;
+  unknownEncodingHandlerData = 0;
+  namespaceSeparator = '!';
+#ifdef XML_DTD
+  parentParser = 0;
+  paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+  ns = 0;
+  poolInit(&tempPool);
+  poolInit(&temp2Pool);
+  protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
+  curBase = 0;
+  if (!dtdInit(&dtd) || !atts || !dataBuf
+      || (encodingName && !protocolEncodingName)) {
+    xmlrpc_XML_ParserFree(parser);
+    return 0;
+  }
+  dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+  xmlrpc_XmlInitEncoding(&initEncoding, &encoding, 0);
+  internalEncoding = XmlGetInternalEncoding();
+  return parser;
+}
+
+XML_Parser
+xmlrpc_XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+{
+  static
+  const XML_Char implicitContext[] = {
+    XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
+    XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
+    XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
+    XML_T('.'), XML_T('w'), XML_T('3'),
+    XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
+    XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
+    XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
+    XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
+    XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
+    XML_T('\0')
+  };
+
+  XML_Parser parser = xmlrpc_XML_ParserCreate(encodingName);
+  if (parser) {
+    XmlInitEncodingNS(&initEncoding, &encoding, 0);
+    ns = 1;
+    internalEncoding = XmlGetInternalEncodingNS();
+    namespaceSeparator = nsSep;
+  }
+  if (!setContext(parser, implicitContext)) {
+    xmlrpc_XML_ParserFree(parser);
+    return 0;
+  }
+  return parser;
+}
+
+int
+xmlrpc_XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+  if (!encodingName)
+    protocolEncodingName = 0;
+  else {
+    protocolEncodingName = poolCopyString(&tempPool, encodingName);
+    if (!protocolEncodingName)
+      return 0;
+  }
+  return 1;
+}
+
+XML_Parser
+xmlrpc_XML_ExternalEntityParserCreate(XML_Parser oldParser,
+                                      const XML_Char *context,
+                                      const XML_Char *encodingName)
+{
+  XML_Parser parser = oldParser;
+  DTD *oldDtd = &dtd;
+  XML_StartElementHandler oldStartElementHandler = startElementHandler;
+  XML_EndElementHandler oldEndElementHandler = endElementHandler;
+  XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
+  XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
+  XML_CommentHandler oldCommentHandler = commentHandler;
+  XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler;
+  XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler;
+  XML_DefaultHandler oldDefaultHandler = defaultHandler;
+  XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
+  XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
+  XML_ExternalParsedEntityDeclHandler oldExternalParsedEntityDeclHandler = externalParsedEntityDeclHandler;
+  XML_InternalParsedEntityDeclHandler oldInternalParsedEntityDeclHandler = internalParsedEntityDeclHandler;
+  XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+  XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+  XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
+  XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
+  XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler;
+  void *oldUserData = userData;
+  void *oldHandlerArg = handlerArg;
+  int oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+  void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+#ifdef XML_DTD
+  int oldParamEntityParsing = paramEntityParsing;
+#endif
+  parser = (ns
+            ? xmlrpc_XML_ParserCreateNS(encodingName, namespaceSeparator)
+            : xmlrpc_XML_ParserCreate(encodingName));
+  if (!parser)
+    return 0;
+  startElementHandler = oldStartElementHandler;
+  endElementHandler = oldEndElementHandler;
+  characterDataHandler = oldCharacterDataHandler;
+  processingInstructionHandler = oldProcessingInstructionHandler;
+  commentHandler = oldCommentHandler;
+  startCdataSectionHandler = oldStartCdataSectionHandler;
+  endCdataSectionHandler = oldEndCdataSectionHandler;
+  defaultHandler = oldDefaultHandler;
+  unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
+  notationDeclHandler = oldNotationDeclHandler;
+  externalParsedEntityDeclHandler = oldExternalParsedEntityDeclHandler;
+  internalParsedEntityDeclHandler = oldInternalParsedEntityDeclHandler;
+  startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
+  endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
+  notStandaloneHandler = oldNotStandaloneHandler;
+  externalEntityRefHandler = oldExternalEntityRefHandler;
+  unknownEncodingHandler = oldUnknownEncodingHandler;
+  userData = oldUserData;
+  if (oldUserData == oldHandlerArg)
+    handlerArg = userData;
+  else
+    handlerArg = parser;
+  if (oldExternalEntityRefHandlerArg != oldParser)
+    externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+  defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+#ifdef XML_DTD
+  paramEntityParsing = oldParamEntityParsing;
+  if (context) {
+#endif /* XML_DTD */
+    if (!dtdCopy(&dtd, oldDtd) || !setContext(parser, context)) {
+      xmlrpc_XML_ParserFree(parser);
+      return 0;
+    }
+    processor = externalEntityInitProcessor;
+#ifdef XML_DTD
+  }
+  else {
+    dtdSwap(&dtd, oldDtd);
+    parentParser = oldParser;
+    XmlPrologStateInitExternalEntity(&prologState);
+    dtd.complete = 1;
+    hadExternalDoctype = 1;
+  }
+#endif /* XML_DTD */
+  return parser;
+}
+
+static
+void destroyBindings(BINDING *bindings)
+{
+  for (;;) {
+    BINDING *b = bindings;
+    if (!b)
+      break;
+    bindings = b->nextTagBinding;
+    free(b->uri);
+    free(b);
+  }
+}
+
+void
+xmlrpc_XML_ParserFree(XML_Parser parser)
+{
+  for (;;) {
+    TAG *p;
+    if (tagStack == 0) {
+      if (freeTagList == 0)
+        break;
+      tagStack = freeTagList;
+      freeTagList = 0;
+    }
+    p = tagStack;
+    tagStack = tagStack->parent;
+    free(p->buf);
+    destroyBindings(p->bindings);
+    free(p);
+  }
+  destroyBindings(freeBindingList);
+  destroyBindings(inheritedBindings);
+  poolDestroy(&tempPool);
+  poolDestroy(&temp2Pool);
+#ifdef XML_DTD
+  if (parentParser) {
+    if (hadExternalDoctype)
+      dtd.complete = 0;
+    dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd);
+  }
+#endif /* XML_DTD */
+  dtdDestroy(&dtd);
+  free((void *)atts);
+  free(groupConnector);
+  free(buffer);
+  free(dataBuf);
+  free(unknownEncodingMem);
+  if (unknownEncodingRelease)
+    unknownEncodingRelease(unknownEncodingData);
+  free(parser);
+}
+
+void
+xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser)
+{
+  handlerArg = parser;
+}
+
+void
+xmlrpc_XML_SetUserData(XML_Parser parser, void *p)
+{
+  if (handlerArg == userData)
+    handlerArg = userData = p;
+  else
+    userData = p;
+}
+
+int
+xmlrpc_XML_SetBase(XML_Parser parser, const XML_Char *p)
+{
+  if (p) {
+    p = poolCopyString(&dtd.pool, p);
+    if (!p)
+      return 0;
+    curBase = p;
+  }
+  else
+    curBase = 0;
+  return 1;
+}
+
+const XML_Char *
+xmlrpc_XML_GetBase(XML_Parser parser)
+{
+  return curBase;
+}
+
+int
+xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser)
+{
+  return nSpecifiedAtts;
+}
+
+int
+xmlrpc_XML_GetIdAttributeIndex(XML_Parser parser)
+{
+  return idAttIndex;
+}
+
+void
+xmlrpc_XML_SetElementHandler(XML_Parser parser,
+                             XML_StartElementHandler start,
+                             XML_EndElementHandler end)
+{
+  startElementHandler = start;
+  endElementHandler = end;
+}
+
+void
+xmlrpc_XML_SetCharacterDataHandler(XML_Parser parser,
+                                   XML_CharacterDataHandler handler)
+{
+  characterDataHandler = handler;
+}
+
+void
+xmlrpc_XML_SetProcessingInstructionHandler(
+    XML_Parser parser,
+    XML_ProcessingInstructionHandler handler)
+{
+  processingInstructionHandler = handler;
+}
+
+void
+xmlrpc_XML_SetCommentHandler(XML_Parser parser,
+                             XML_CommentHandler handler)
+{
+  commentHandler = handler;
+}
+
+void
+xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser,
+                                  XML_StartCdataSectionHandler start,
+                                  XML_EndCdataSectionHandler end)
+{
+  startCdataSectionHandler = start;
+  endCdataSectionHandler = end;
+}
+
+void
+xmlrpc_XML_SetDefaultHandler(XML_Parser parser,
+                             XML_DefaultHandler handler)
+{
+  defaultHandler = handler;
+  defaultExpandInternalEntities = 0;
+}
+
+void
+xmlrpc_XML_SetDefaultHandlerExpand(XML_Parser parser,
+                                   XML_DefaultHandler handler)
+{
+  defaultHandler = handler;
+  defaultExpandInternalEntities = 1;
+}
+
+void
+xmlrpc_XML_SetDoctypeDeclHandler(XML_Parser parser,
+                                 XML_StartDoctypeDeclHandler start,
+                                 XML_EndDoctypeDeclHandler end)
+{
+  startDoctypeDeclHandler = start;
+  endDoctypeDeclHandler = end;
+}
+
+void
+xmlrpc_XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+                                        XML_UnparsedEntityDeclHandler handler)
+{
+  unparsedEntityDeclHandler = handler;
+}
+
+void
+xmlrpc_XML_SetExternalParsedEntityDeclHandler(
+    XML_Parser parser,
+    XML_ExternalParsedEntityDeclHandler handler)
+{
+  externalParsedEntityDeclHandler = handler;
+}
+
+void
+xmlrpc_XML_SetInternalParsedEntityDeclHandler(
+    XML_Parser parser,
+    XML_InternalParsedEntityDeclHandler handler)
+{
+  internalParsedEntityDeclHandler = handler;
+}
+
+void
+xmlrpc_XML_SetNotationDeclHandler(XML_Parser parser,
+                                  XML_NotationDeclHandler handler)
+{
+  notationDeclHandler = handler;
+}
+
+void
+xmlrpc_XML_SetNamespaceDeclHandler(XML_Parser parser,
+                                   XML_StartNamespaceDeclHandler start,
+                                   XML_EndNamespaceDeclHandler end)
+{
+  startNamespaceDeclHandler = start;
+  endNamespaceDeclHandler = end;
+}
+
+void
+xmlrpc_XML_SetNotStandaloneHandler(XML_Parser parser,
+                                   XML_NotStandaloneHandler handler)
+{
+  notStandaloneHandler = handler;
+}
+
+void
+xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser,
+                                       XML_ExternalEntityRefHandler handler)
+{
+  externalEntityRefHandler = handler;
+}
+
+void
+xmlrpc_XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
+{
+  if (arg)
+    externalEntityRefHandlerArg = arg;
+  else
+    externalEntityRefHandlerArg = parser;
+}
+
+void
+xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser,
+                                     XML_UnknownEncodingHandler handler,
+                                     void *data)
+{
+  unknownEncodingHandler = handler;
+  unknownEncodingHandlerData = data;
+}
+
+
+
+int
+xmlrpc_XML_SetParamEntityParsing(
+    XML_Parser                  const parser  ATTR_UNUSED,
+    enum XML_ParamEntityParsing const parsing) {
+    
+    int retval;
+
+#ifdef XML_DTD
+    paramEntityParsing = parsing;
+    retval = 1;
+#else
+    retval = parsing == XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+
+    return retval;
+}
+
+
+
+int
+xmlrpc_XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+{
+  if (len == 0) {
+    if (!isFinal)
+      return 1;
+    positionPtr = bufferPtr;
+    errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
+    if (errorCode == XML_ERROR_NONE)
+      return 1;
+    eventEndPtr = eventPtr;
+    processor = errorProcessor;
+    return 0;
+  }
+  else if (bufferPtr == bufferEnd) {
+    const char *end;
+    int nLeftOver;
+    parseEndByteIndex += len;
+    positionPtr = s;
+    if (isFinal) {
+      errorCode = processor(parser, s, parseEndPtr = s + len, 0);
+      if (errorCode == XML_ERROR_NONE)
+        return 1;
+      eventEndPtr = eventPtr;
+      processor = errorProcessor;
+      return 0;
+    }
+    errorCode = processor(parser, s, parseEndPtr = s + len, &end);
+    if (errorCode != XML_ERROR_NONE) {
+      eventEndPtr = eventPtr;
+      processor = errorProcessor;
+      return 0;
+    }
+    XmlUpdatePosition(encoding, positionPtr, end, &position);
+    nLeftOver = s + len - end;
+    if (nLeftOver) {
+      if (buffer == 0 || nLeftOver > bufferLim - buffer) {
+        /* FIXME avoid integer overflow */
+        buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2);
+        /* FIXME storage leak if realloc fails */
+        if (!buffer) {
+          errorCode = XML_ERROR_NO_MEMORY;
+          eventPtr = eventEndPtr = 0;
+          processor = errorProcessor;
+          return 0;
+        }
+        bufferLim = buffer + len * 2;
+      }
+      memcpy(buffer, end, nLeftOver);
+      bufferPtr = buffer;
+      bufferEnd = buffer + nLeftOver;
+    }
+    return 1;
+  }
+  else {
+    memcpy(xmlrpc_XML_GetBuffer(parser, len), s, len);
+    return xmlrpc_XML_ParseBuffer(parser, len, isFinal);
+  }
+}
+
+int
+xmlrpc_XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+{
+  const char *start = bufferPtr;
+  positionPtr = start;
+  bufferEnd += len;
+  parseEndByteIndex += len;
+  errorCode = processor(parser, start, parseEndPtr = bufferEnd,
+                        isFinal ? (const char **)0 : &bufferPtr);
+  if (errorCode == XML_ERROR_NONE) {
+    if (!isFinal)
+      XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+    return 1;
+  }
+  else {
+    eventEndPtr = eventPtr;
+    processor = errorProcessor;
+    return 0;
+  }
+}
+
+void *
+xmlrpc_XML_GetBuffer(XML_Parser parser, int len)
+{
+  if (len > bufferLim - bufferEnd) {
+    /* FIXME avoid integer overflow */
+    int neededSize = len + (bufferEnd - bufferPtr);
+    if (neededSize  <= bufferLim - buffer) {
+      memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+      bufferEnd = buffer + (bufferEnd - bufferPtr);
+      bufferPtr = buffer;
+    }
+    else {
+      char *newBuf;
+      int bufferSize = bufferLim - bufferPtr;
+      if (bufferSize == 0)
+        bufferSize = INIT_BUFFER_SIZE;
+      do {
+        bufferSize *= 2;
+      } while (bufferSize < neededSize);
+      newBuf = malloc(bufferSize);
+      if (newBuf == 0) {
+        errorCode = XML_ERROR_NO_MEMORY;
+        return 0;
+      }
+      bufferLim = newBuf + bufferSize;
+      if (bufferPtr) {
+        memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+        free(buffer);
+      }
+      bufferEnd = newBuf + (bufferEnd - bufferPtr);
+      bufferPtr = buffer = newBuf;
+    }
+  }
+  return bufferEnd;
+}
+
+enum XML_Error
+xmlrpc_XML_GetErrorCode(XML_Parser parser)
+{
+  return errorCode;
+}
+
+long
+xmlrpc_XML_GetCurrentByteIndex(XML_Parser parser)
+{
+  if (eventPtr)
+    return parseEndByteIndex - (parseEndPtr - eventPtr);
+  return -1;
+}
+
+int
+xmlrpc_XML_GetCurrentByteCount(XML_Parser parser)
+{
+  if (eventEndPtr && eventPtr)
+    return eventEndPtr - eventPtr;
+  return 0;
+}
+
+int
+xmlrpc_XML_GetCurrentLineNumber(XML_Parser parser)
+{
+  if (eventPtr) {
+    XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+    positionPtr = eventPtr;
+  }
+  return position.lineNumber + 1;
+}
+
+int
+xmlrpc_XML_GetCurrentColumnNumber(XML_Parser parser)
+{
+  if (eventPtr) {
+    XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+    positionPtr = eventPtr;
+  }
+  return position.columnNumber;
+}
+
+void
+xmlrpc_XML_DefaultCurrent(XML_Parser parser)
+{
+  if (defaultHandler) {
+    if (openInternalEntities)
+      reportDefault(parser,
+                    internalEncoding,
+                    openInternalEntities->internalEventPtr,
+                    openInternalEntities->internalEventEndPtr);
+    else
+      reportDefault(parser, encoding, eventPtr, eventEndPtr);
+  }
+}
+
+const XML_LChar *
+xmlrpc_XML_ErrorString(int const code) {
+
+    static const XML_LChar * const message[] = {
+        NULL,
+        XML_T("out of memory"),
+        XML_T("syntax error"),
+        XML_T("no element found"),
+        XML_T("not well-formed"),
+        XML_T("unclosed token"),
+        XML_T("unclosed token"),
+        XML_T("mismatched tag"),
+        XML_T("duplicate attribute"),
+        XML_T("junk after document element"),
+        XML_T("illegal parameter entity reference"),
+        XML_T("undefined entity"),
+        XML_T("recursive entity reference"),
+        XML_T("asynchronous entity"),
+        XML_T("reference to invalid character number"),
+        XML_T("reference to binary entity"),
+        XML_T("reference to external entity in attribute"),
+        XML_T("xml processing instruction not at start of external entity"),
+        XML_T("unknown encoding"),
+        XML_T("encoding specified in XML declaration is incorrect"),
+        XML_T("unclosed CDATA section"),
+        XML_T("error in processing external entity reference"),
+        XML_T("document is not standalone")
+    };
+
+    const XML_LChar * retval;
+
+    if (code > 0 && (unsigned)code < ARRAY_SIZE(message))
+        retval = message[code];
+    else
+        retval = NULL;
+    
+    return retval;
+}
+
+static
+enum XML_Error contentProcessor(XML_Parser parser,
+                                const char *start,
+                                const char *end,
+                                const char **endPtr)
+{
+  return doContent(parser, 0, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor(XML_Parser parser,
+                                           const char *start,
+                                           const char *end,
+                                           const char **endPtr)
+{
+  enum XML_Error result = initializeEncoding(parser);
+  if (result != XML_ERROR_NONE)
+    return result;
+  processor = externalEntityInitProcessor2;
+  return externalEntityInitProcessor2(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor2(XML_Parser parser,
+                                            const char *start,
+                                            const char *end,
+                                            const char **endPtr)
+{
+  const char *next;
+  int tok = XmlContentTok(encoding, start, end, &next);
+  switch (tok) {
+  case XML_TOK_BOM:
+    start = next;
+    break;
+  case XML_TOK_PARTIAL:
+    if (endPtr) {
+      *endPtr = start;
+      return XML_ERROR_NONE;
+    }
+    eventPtr = start;
+    return XML_ERROR_UNCLOSED_TOKEN;
+  case XML_TOK_PARTIAL_CHAR:
+    if (endPtr) {
+      *endPtr = start;
+      return XML_ERROR_NONE;
+    }
+    eventPtr = start;
+    return XML_ERROR_PARTIAL_CHAR;
+  }
+  processor = externalEntityInitProcessor3;
+  return externalEntityInitProcessor3(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor3(XML_Parser parser,
+                                            const char *start,
+                                            const char *end,
+                                            const char **endPtr)
+{
+  const char *next;
+  int tok = XmlContentTok(encoding, start, end, &next);
+  switch (tok) {
+  case XML_TOK_XML_DECL:
+    {
+      enum XML_Error result = processXmlDecl(parser, 1, start, next);
+      if (result != XML_ERROR_NONE)
+        return result;
+      start = next;
+    }
+    break;
+  case XML_TOK_PARTIAL:
+    if (endPtr) {
+      *endPtr = start;
+      return XML_ERROR_NONE;
+    }
+    eventPtr = start;
+    return XML_ERROR_UNCLOSED_TOKEN;
+  case XML_TOK_PARTIAL_CHAR:
+    if (endPtr) {
+      *endPtr = start;
+      return XML_ERROR_NONE;
+    }
+    eventPtr = start;
+    return XML_ERROR_PARTIAL_CHAR;
+  }
+  processor = externalEntityContentProcessor;
+  tagLevel = 1;
+  return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityContentProcessor(XML_Parser parser,
+                                              const char *start,
+                                              const char *end,
+                                              const char **endPtr)
+{
+  return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static enum XML_Error
+doContent(XML_Parser parser,
+          int startTagLevel,
+          const ENCODING *enc,
+          const char *s,
+          const char *end,
+          const char **nextPtr)
+{
+  const char **eventPP;
+  const char **eventEndPP;
+  if (enc == encoding) {
+    eventPP = &eventPtr;
+    eventEndPP = &eventEndPtr;
+  }
+  else {
+    eventPP = &(openInternalEntities->internalEventPtr);
+    eventEndPP = &(openInternalEntities->internalEventEndPtr);
+  }
+  *eventPP = s;
+  for (;;) {
+    const char *next = s; /* XmlContentTok doesn't always set the last arg */
+    int tok = XmlContentTok(enc, s, end, &next);
+    *eventEndPP = next;
+    switch (tok) {
+    case XML_TOK_TRAILING_CR:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      *eventEndPP = end;
+      if (characterDataHandler) {
+        XML_Char c = 0xA;
+        characterDataHandler(handlerArg, &c, 1);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, end);
+      if (startTagLevel == 0)
+        return XML_ERROR_NO_ELEMENTS;
+      if (tagLevel != startTagLevel)
+        return XML_ERROR_ASYNC_ENTITY;
+      return XML_ERROR_NONE;
+    case XML_TOK_NONE:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      if (startTagLevel > 0) {
+        if (tagLevel != startTagLevel)
+          return XML_ERROR_ASYNC_ENTITY;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_NO_ELEMENTS;
+    case XML_TOK_INVALID:
+      *eventPP = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_UNCLOSED_TOKEN;
+    case XML_TOK_PARTIAL_CHAR:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_PARTIAL_CHAR;
+    case XML_TOK_ENTITY_REF:
+      {
+        const XML_Char *name;
+        ENTITY *entity;
+        XML_Char ch = XmlPredefinedEntityName(enc,
+                                              s + enc->minBytesPerChar,
+                                              next - enc->minBytesPerChar);
+        if (ch) {
+          if (characterDataHandler)
+            characterDataHandler(handlerArg, &ch, 1);
+          else if (defaultHandler)
+            reportDefault(parser, enc, s, next);
+          break;
+        }
+        name = poolStoreString(&dtd.pool, enc,
+                                s + enc->minBytesPerChar,
+                                next - enc->minBytesPerChar);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+        poolDiscard(&dtd.pool);
+        if (!entity) {
+          if (dtd.complete || dtd.standalone)
+            return XML_ERROR_UNDEFINED_ENTITY;
+          if (defaultHandler)
+            reportDefault(parser, enc, s, next);
+          break;
+        }
+        if (entity->open)
+          return XML_ERROR_RECURSIVE_ENTITY_REF;
+        if (entity->notation)
+          return XML_ERROR_BINARY_ENTITY_REF;
+        if (entity) {
+          if (entity->textPtr) {
+            enum XML_Error result;
+            OPEN_INTERNAL_ENTITY openEntity;
+            if (defaultHandler && !defaultExpandInternalEntities) {
+              reportDefault(parser, enc, s, next);
+              break;
+            }
+            entity->open = 1;
+            openEntity.next = openInternalEntities;
+            openInternalEntities = &openEntity;
+            openEntity.entity = entity;
+            openEntity.internalEventPtr = 0;
+            openEntity.internalEventEndPtr = 0;
+            result = doContent(parser,
+                               tagLevel,
+                               internalEncoding,
+                               (char *)entity->textPtr,
+                               (char *)(entity->textPtr + entity->textLen),
+                               0);
+            entity->open = 0;
+            openInternalEntities = openEntity.next;
+            if (result)
+              return result;
+          }
+          else if (externalEntityRefHandler) {
+            const XML_Char *context;
+            entity->open = 1;
+            context = getContext(parser);
+            entity->open = 0;
+            if (!context)
+              return XML_ERROR_NO_MEMORY;
+            if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+                                          context,
+                                          entity->base,
+                                          entity->systemId,
+                                          entity->publicId))
+              return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+            poolDiscard(&tempPool);
+          }
+          else if (defaultHandler)
+            reportDefault(parser, enc, s, next);
+        }
+        break;
+      }
+    case XML_TOK_START_TAG_WITH_ATTS:
+      if (!startElementHandler) {
+        enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+        if (result)
+          return result;
+      }
+      /* fall through */
+    case XML_TOK_START_TAG_NO_ATTS:
+      {
+        TAG *tag;
+        if (freeTagList) {
+          tag = freeTagList;
+          freeTagList = freeTagList->parent;
+        }
+        else {
+          tag = malloc(sizeof(TAG));
+          if (!tag)
+            return XML_ERROR_NO_MEMORY;
+          tag->buf = malloc(INIT_TAG_BUF_SIZE);
+          if (!tag->buf)
+            return XML_ERROR_NO_MEMORY;
+          tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+        }
+        tag->bindings = 0;
+        tag->parent = tagStack;
+        tagStack = tag;
+        tag->name.localPart = 0;
+        tag->rawName = s + enc->minBytesPerChar;
+        tag->rawNameLength = XmlNameLength(enc, tag->rawName);
+        if (nextPtr) {
+          /* Need to guarantee that:
+             tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
+          if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
+            int bufSize = tag->rawNameLength * 4;
+            bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
+            tag->buf = realloc(tag->buf, bufSize);
+            if (!tag->buf)
+              return XML_ERROR_NO_MEMORY;
+            tag->bufEnd = tag->buf + bufSize;
+          }
+          memcpy(tag->buf, tag->rawName, tag->rawNameLength);
+          tag->rawName = tag->buf;
+        }
+        ++tagLevel;
+        if (startElementHandler) {
+          enum XML_Error result;
+          XML_Char *toPtr;
+          for (;;) {
+            const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+            const char *fromPtr = tag->rawName;
+            int bufSize;
+            if (nextPtr)
+              toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
+            else
+              toPtr = (XML_Char *)tag->buf;
+            tag->name.str = toPtr;
+            XmlConvert(enc,
+                       &fromPtr, rawNameEnd,
+                       (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+            if (fromPtr == rawNameEnd)
+              break;
+            bufSize = (tag->bufEnd - tag->buf) << 1;
+            tag->buf = realloc(tag->buf, bufSize);
+            if (!tag->buf)
+              return XML_ERROR_NO_MEMORY;
+            tag->bufEnd = tag->buf + bufSize;
+            if (nextPtr)
+              tag->rawName = tag->buf;
+          }
+          *toPtr = XML_T('\0');
+          result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+          if (result)
+            return result;
+          startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
+          poolClear(&tempPool);
+        }
+        else {
+          tag->name.str = 0;
+          if (defaultHandler)
+            reportDefault(parser, enc, s, next);
+        }
+        break;
+      }
+    case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+      if (!startElementHandler) {
+        enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+        if (result)
+          return result;
+      }
+      /* fall through */
+    case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+      if (startElementHandler || endElementHandler) {
+        const char *rawName = s + enc->minBytesPerChar;
+        enum XML_Error result;
+        BINDING *bindings = 0;
+        TAG_NAME name;
+        name.str = poolStoreString(&tempPool, enc, rawName,
+                                   rawName + XmlNameLength(enc, rawName));
+        if (!name.str)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&tempPool);
+        result = storeAtts(parser, enc, s, &name, &bindings);
+        if (result)
+          return result;
+        poolFinish(&tempPool);
+        if (startElementHandler)
+          startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
+        if (endElementHandler) {
+          if (startElementHandler)
+            *eventPP = *eventEndPP;
+          endElementHandler(handlerArg, name.str);
+        }
+        poolClear(&tempPool);
+        while (bindings) {
+          BINDING *b = bindings;
+          if (endNamespaceDeclHandler)
+            endNamespaceDeclHandler(handlerArg, b->prefix->name);
+          bindings = bindings->nextTagBinding;
+          b->nextTagBinding = freeBindingList;
+          freeBindingList = b;
+          b->prefix->binding = b->prevPrefixBinding;
+        }
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      if (tagLevel == 0)
+        return epilogProcessor(parser, next, end, nextPtr);
+      break;
+    case XML_TOK_END_TAG:
+      if (tagLevel == startTagLevel)
+        return XML_ERROR_ASYNC_ENTITY;
+      else {
+        int len;
+        const char *rawName;
+        TAG *tag = tagStack;
+        tagStack = tag->parent;
+        tag->parent = freeTagList;
+        freeTagList = tag;
+        rawName = s + enc->minBytesPerChar*2;
+        len = XmlNameLength(enc, rawName);
+        if (len != tag->rawNameLength
+            || memcmp(tag->rawName, rawName, len) != 0) {
+          *eventPP = rawName;
+          return XML_ERROR_TAG_MISMATCH;
+        }
+        --tagLevel;
+        if (endElementHandler && tag->name.str) {
+          if (tag->name.localPart) {
+            XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
+            const XML_Char *from = tag->name.localPart;
+            while ((*to++ = *from++) != 0)
+              ;
+          }
+          endElementHandler(handlerArg, tag->name.str);
+        }
+        else if (defaultHandler)
+          reportDefault(parser, enc, s, next);
+        while (tag->bindings) {
+          BINDING *b = tag->bindings;
+          if (endNamespaceDeclHandler)
+            endNamespaceDeclHandler(handlerArg, b->prefix->name);
+          tag->bindings = tag->bindings->nextTagBinding;
+          b->nextTagBinding = freeBindingList;
+          freeBindingList = b;
+          b->prefix->binding = b->prevPrefixBinding;
+        }
+        if (tagLevel == 0)
+          return epilogProcessor(parser, next, end, nextPtr);
+      }
+      break;
+    case XML_TOK_CHAR_REF:
+      {
+        int n = XmlCharRefNumber(enc, s);
+        if (n < 0)
+          return XML_ERROR_BAD_CHAR_REF;
+        if (characterDataHandler) {
+          XML_Char buf[XML_ENCODE_MAX];
+          characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
+        }
+        else if (defaultHandler)
+          reportDefault(parser, enc, s, next);
+      }
+      break;
+    case XML_TOK_XML_DECL:
+      return XML_ERROR_MISPLACED_XML_PI;
+    case XML_TOK_DATA_NEWLINE:
+      if (characterDataHandler) {
+        XML_Char c = 0xA;
+        characterDataHandler(handlerArg, &c, 1);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_TOK_CDATA_SECT_OPEN:
+      {
+        enum XML_Error result;
+        if (startCdataSectionHandler)
+          startCdataSectionHandler(handlerArg);
+#if 0
+        /* Suppose you doing a transformation on a document that involves
+           changing only the character data.  You set up a defaultHandler
+           and a characterDataHandler.  The defaultHandler simply copies
+           characters through.  The characterDataHandler does the transformation
+           and writes the characters out escaping them as necessary.  This case
+           will fail to work if we leave out the following two lines (because &
+           and < inside CDATA sections will be incorrectly escaped).
+
+           However, now we have a start/endCdataSectionHandler, so it seems
+           easier to let the user deal with this. */
+
+        else if (characterDataHandler)
+          characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+        else if (defaultHandler)
+          reportDefault(parser, enc, s, next);
+        result = doCdataSection(parser, enc, &next, end, nextPtr);
+        if (!next) {
+          processor = cdataSectionProcessor;
+          return result;
+        }
+      }
+      break;
+    case XML_TOK_TRAILING_RSQB:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      if (characterDataHandler) {
+        if (MUST_CONVERT(enc, s)) {
+          ICHAR *dataPtr = (ICHAR *)dataBuf;
+          XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+          characterDataHandler(handlerArg, dataBuf,
+                               dataPtr - (ICHAR *)dataBuf);
+        }
+        else
+          characterDataHandler(handlerArg,
+                               (XML_Char *)s,
+                               (XML_Char *)end - (XML_Char *)s);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, end);
+      if (startTagLevel == 0) {
+        *eventPP = end;
+        return XML_ERROR_NO_ELEMENTS;
+      }
+      if (tagLevel != startTagLevel) {
+        *eventPP = end;
+        return XML_ERROR_ASYNC_ENTITY;
+      }
+      return XML_ERROR_NONE;
+    case XML_TOK_DATA_CHARS:
+      if (characterDataHandler) {
+        if (MUST_CONVERT(enc, s)) {
+          for (;;) {
+            ICHAR *dataPtr = (ICHAR *)dataBuf;
+            XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+            *eventEndPP = s;
+            characterDataHandler(handlerArg, dataBuf,
+                                 dataPtr - (ICHAR *)dataBuf);
+            if (s == next)
+              break;
+            *eventPP = s;
+          }
+        }
+        else
+          characterDataHandler(handlerArg,
+                               (XML_Char *)s,
+                               (XML_Char *)next - (XML_Char *)s);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_TOK_PI:
+      if (!reportProcessingInstruction(parser, enc, s, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_COMMENT:
+      if (!reportComment(parser, enc, s, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    default:
+      if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    }
+    *eventPP = s = next;
+  }
+  /* not reached */
+}
+
+/* If tagNamePtr is non-null, build a real list of attributes,
+otherwise just check the attributes for well-formedness. */
+
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
+                                const char *attStr, TAG_NAME *tagNamePtr,
+                                BINDING **bindingsPtr)
+{
+  ELEMENT_TYPE *elementType = 0;
+  int nDefaultAtts = 0;
+  const XML_Char ** appAtts;
+      /* the attribute list to pass to the application */
+  int attIndex = 0;
+  int i;
+  int n;
+  int nPrefixes = 0;
+  BINDING *binding;
+  const XML_Char *localPart;
+
+  /* lookup the element type name */
+  if (tagNamePtr) {
+    elementType = (ELEMENT_TYPE *)
+        lookup(&dtd.elementTypes, tagNamePtr->str, 0);
+    if (!elementType) {
+      tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
+      if (!tagNamePtr->str)
+        return XML_ERROR_NO_MEMORY;
+      elementType = (ELEMENT_TYPE *)
+          lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
+      if (!elementType)
+        return XML_ERROR_NO_MEMORY;
+      if (ns && !setElementTypePrefix(parser, elementType))
+        return XML_ERROR_NO_MEMORY;
+    }
+    nDefaultAtts = elementType->nDefaultAtts;
+  }
+  /* get the attributes from the tokenizer */
+  n = XmlGetAttributes(enc, attStr, attsSize, atts);
+  if (n + nDefaultAtts > attsSize) {
+    int oldAttsSize = attsSize;
+    attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+    atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE));
+    if (!atts)
+      return XML_ERROR_NO_MEMORY;
+    if (n > oldAttsSize)
+      XmlGetAttributes(enc, attStr, n, atts);
+  }
+  appAtts = (const XML_Char **)atts;
+  for (i = 0; i < n; i++) {
+    /* add the name and value to the attribute list */
+    ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
+                                         atts[i].name
+                                         + XmlNameLength(enc, atts[i].name));
+    if (!attId)
+      return XML_ERROR_NO_MEMORY;
+    /* detect duplicate attributes */
+    if ((attId->name)[-1]) {
+      if (enc == encoding)
+        eventPtr = atts[i].name;
+      return XML_ERROR_DUPLICATE_ATTRIBUTE;
+    }
+    (attId->name)[-1] = 1;
+    appAtts[attIndex++] = attId->name;
+    if (!atts[i].normalized) {
+      enum XML_Error result;
+      int isCdata = 1;
+
+      /* figure out whether declared as other than CDATA */
+      if (attId->maybeTokenized) {
+        int j;
+        for (j = 0; j < nDefaultAtts; j++) {
+          if (attId == elementType->defaultAtts[j].id) {
+            isCdata = elementType->defaultAtts[j].isCdata;
+            break;
+          }
+        }
+      }
+
+      /* normalize the attribute value */
+      result = storeAttributeValue(parser, enc, isCdata,
+                                   atts[i].valuePtr, atts[i].valueEnd,
+                                   &tempPool);
+      if (result)
+        return result;
+      if (tagNamePtr) {
+        appAtts[attIndex] = poolStart(&tempPool);
+        poolFinish(&tempPool);
+      }
+      else
+        poolDiscard(&tempPool);
+    }
+    else if (tagNamePtr) {
+      /* the value did not need normalizing */
+      appAtts[attIndex] =
+          poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
+      if (appAtts[attIndex] == 0)
+        return XML_ERROR_NO_MEMORY;
+      poolFinish(&tempPool);
+    }
+    /* handle prefixed attribute names */
+    if (attId->prefix && tagNamePtr) {
+      if (attId->xmlns) {
+        /* deal with namespace declarations here */
+        if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex],
+                        bindingsPtr))
+          return XML_ERROR_NO_MEMORY;
+        --attIndex;
+      }
+      else {
+        /* deal with other prefixed names later */
+        attIndex++;
+        nPrefixes++;
+        (attId->name)[-1] = 2;
+      }
+    }
+    else
+      attIndex++;
+  }
+  if (tagNamePtr) {
+    int j;
+    nSpecifiedAtts = attIndex;
+    if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
+      for (i = 0; i < attIndex; i += 2)
+        if (appAtts[i] == elementType->idAtt->name) {
+          idAttIndex = i;
+          break;
+        }
+    }
+    else
+      idAttIndex = -1;
+    /* do attribute defaulting */
+    for (j = 0; j < nDefaultAtts; j++) {
+      const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
+      if (!(da->id->name)[-1] && da->value) {
+        if (da->id->prefix) {
+          if (da->id->xmlns) {
+            if (!addBinding(parser, da->id->prefix, da->id, da->value,
+                            bindingsPtr))
+              return XML_ERROR_NO_MEMORY;
+          }
+          else {
+            (da->id->name)[-1] = 2;
+            nPrefixes++;
+            appAtts[attIndex++] = da->id->name;
+            appAtts[attIndex++] = da->value;
+          }
+        }
+        else {
+          (da->id->name)[-1] = 1;
+          appAtts[attIndex++] = da->id->name;
+          appAtts[attIndex++] = da->value;
+        }
+      }
+    }
+    appAtts[attIndex] = 0;
+  }
+  i = 0;
+  if (nPrefixes) {
+    /* expand prefixed attribute names */
+    for (; i < attIndex; i += 2) {
+      if (appAtts[i][-1] == 2) {
+        ATTRIBUTE_ID *id;
+        ((XML_Char *)(appAtts[i]))[-1] = 0;
+        id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
+        if (id->prefix->binding) {
+          int j;
+          const BINDING *b = id->prefix->binding;
+          const XML_Char *s = appAtts[i];
+          for (j = 0; j < b->uriLen; j++) {
+            if (!poolAppendChar(&tempPool, b->uri[j]))
+              return XML_ERROR_NO_MEMORY;
+          }
+          while (*s++ != ':')
+            ;
+          do {
+            if (!poolAppendChar(&tempPool, *s))
+              return XML_ERROR_NO_MEMORY;
+          } while (*s++);
+          appAtts[i] = poolStart(&tempPool);
+          poolFinish(&tempPool);
+        }
+        if (!--nPrefixes)
+          break;
+      }
+      else
+        ((XML_Char *)(appAtts[i]))[-1] = 0;
+    }
+  }
+  /* clear the flags that say whether attributes were specified */
+  for (; i < attIndex; i += 2)
+    ((XML_Char *)(appAtts[i]))[-1] = 0;
+  if (!tagNamePtr)
+    return XML_ERROR_NONE;
+  for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
+    binding->attId->name[-1] = 0;
+  /* expand the element type name */
+  if (elementType->prefix) {
+    binding = elementType->prefix->binding;
+    if (!binding)
+      return XML_ERROR_NONE;
+    localPart = tagNamePtr->str;
+    while (*localPart++ != XML_T(':'))
+      ;
+  }
+  else if (dtd.defaultPrefix.binding) {
+    binding = dtd.defaultPrefix.binding;
+    localPart = tagNamePtr->str;
+  }
+  else
+    return XML_ERROR_NONE;
+  tagNamePtr->localPart = localPart;
+  tagNamePtr->uriLen = binding->uriLen;
+  for (i = 0; localPart[i++];)
+    ;
+  n = i + binding->uriLen;
+  if (n > binding->uriAlloc) {
+    TAG *p;
+    XML_Char *uri = malloc((n + EXPAND_SPARE) * sizeof(XML_Char));
+    if (!uri)
+      return XML_ERROR_NO_MEMORY;
+    binding->uriAlloc = n + EXPAND_SPARE;
+    memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
+    for (p = tagStack; p; p = p->parent)
+      if (p->name.str == binding->uri)
+        p->name.str = uri;
+    free(binding->uri);
+    binding->uri = uri;
+  }
+  memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char));
+  tagNamePtr->str = binding->uri;
+  return XML_ERROR_NONE;
+}
+
+static
+int addBinding(XML_Parser parser,
+               PREFIX *prefix,
+               const ATTRIBUTE_ID *attId,
+               const XML_Char *uri,
+               BINDING **bindingsPtr)
+{
+  BINDING *b;
+  int len;
+  for (len = 0; uri[len]; len++)
+    ;
+  if (namespaceSeparator)
+    len++;
+  if (freeBindingList) {
+    b = freeBindingList;
+    if (len > b->uriAlloc) {
+      b->uri = realloc(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
+      if (!b->uri)
+        return 0;
+      b->uriAlloc = len + EXPAND_SPARE;
+    }
+    freeBindingList = b->nextTagBinding;
+  }
+  else {
+    b = malloc(sizeof(BINDING));
+    if (!b)
+      return 0;
+    b->uri = malloc(sizeof(XML_Char) * (len + EXPAND_SPARE));
+    if (!b->uri) {
+      free(b);
+      return 0;
+    }
+    b->uriAlloc = len + EXPAND_SPARE;
+  }
+  b->uriLen = len;
+  memcpy(b->uri, uri, len * sizeof(XML_Char));
+  if (namespaceSeparator)
+    b->uri[len - 1] = namespaceSeparator;
+  b->prefix = prefix;
+  b->attId = attId;
+  b->prevPrefixBinding = prefix->binding;
+  if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
+    prefix->binding = 0;
+  else
+    prefix->binding = b;
+  b->nextTagBinding = *bindingsPtr;
+  *bindingsPtr = b;
+  if (startNamespaceDeclHandler)
+    startNamespaceDeclHandler(handlerArg, prefix->name,
+                              prefix->binding ? uri : 0);
+  return 1;
+}
+
+/* The idea here is to avoid using stack for each CDATA section when
+the whole file is parsed with one call. */
+
+static
+enum XML_Error cdataSectionProcessor(XML_Parser parser,
+                                     const char *start,
+                                     const char *end,
+                                     const char **endPtr)
+{
+  enum XML_Error result =
+      doCdataSection(parser, encoding, &start, end, endPtr);
+  if (start) {
+    processor = contentProcessor;
+    return contentProcessor(parser, start, end, endPtr);
+  }
+  return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null if
+the section is not yet closed. */
+
+static
+enum XML_Error doCdataSection(XML_Parser parser,
+                              const ENCODING *enc,
+                              const char **startPtr,
+                              const char *end,
+                              const char **nextPtr)
+{
+  const char *s = *startPtr;
+  const char **eventPP;
+  const char **eventEndPP;
+  if (enc == encoding) {
+    eventPP = &eventPtr;
+    *eventPP = s;
+    eventEndPP = &eventEndPtr;
+  }
+  else {
+    eventPP = &(openInternalEntities->internalEventPtr);
+    eventEndPP = &(openInternalEntities->internalEventEndPtr);
+  }
+  *eventPP = s;
+  *startPtr = 0;
+  for (;;) {
+    const char *next;
+    int tok = XmlCdataSectionTok(enc, s, end, &next);
+    *eventEndPP = next;
+    switch (tok) {
+    case XML_TOK_CDATA_SECT_CLOSE:
+      if (endCdataSectionHandler)
+        endCdataSectionHandler(handlerArg);
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      *startPtr = next;
+      return XML_ERROR_NONE;
+    case XML_TOK_DATA_NEWLINE:
+      if (characterDataHandler) {
+        XML_Char c = 0xA;
+        characterDataHandler(handlerArg, &c, 1);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_TOK_DATA_CHARS:
+      if (characterDataHandler) {
+        if (MUST_CONVERT(enc, s)) {
+          for (;;) {
+            ICHAR *dataPtr = (ICHAR *)dataBuf;
+            XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+            *eventEndPP = next;
+            characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+            if (s == next)
+              break;
+            *eventPP = s;
+          }
+        }
+        else
+          characterDataHandler(handlerArg,
+                               (XML_Char *)s,
+                               (XML_Char *)next - (XML_Char *)s);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_TOK_INVALID:
+      *eventPP = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL_CHAR:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_PARTIAL_CHAR;
+    case XML_TOK_PARTIAL:
+    case XML_TOK_NONE:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_UNCLOSED_CDATA_SECTION;
+    default:
+      abort();
+    }
+    *eventPP = s = next;
+  }
+  /* not reached */
+}
+
+#ifdef XML_DTD
+
+/* The idea here is to avoid using stack for each IGNORE section when
+the whole file is parsed with one call. */
+
+static
+enum XML_Error ignoreSectionProcessor(XML_Parser parser,
+                                      const char *start,
+                                      const char *end,
+                                      const char **endPtr)
+{
+  enum XML_Error result =
+      doIgnoreSection(parser, encoding, &start, end, endPtr);
+  if (start) {
+    processor = prologProcessor;
+    return prologProcessor(parser, start, end, endPtr);
+  }
+  return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null if
+the section is not yet closed. */
+
+static
+enum XML_Error doIgnoreSection(XML_Parser parser,
+                               const ENCODING *enc,
+                               const char **startPtr,
+                               const char *end,
+                               const char **nextPtr)
+{
+  const char *next;
+  int tok;
+  const char *s = *startPtr;
+  const char **eventPP;
+  const char **eventEndPP;
+  if (enc == encoding) {
+    eventPP = &eventPtr;
+    *eventPP = s;
+    eventEndPP = &eventEndPtr;
+  }
+  else {
+    eventPP = &(openInternalEntities->internalEventPtr);
+    eventEndPP = &(openInternalEntities->internalEventEndPtr);
+  }
+  *eventPP = s;
+  *startPtr = 0;
+  tok = XmlIgnoreSectionTok(enc, s, end, &next);
+  *eventEndPP = next;
+  switch (tok) {
+  case XML_TOK_IGNORE_SECT:
+    if (defaultHandler)
+      reportDefault(parser, enc, s, next);
+    *startPtr = next;
+    return XML_ERROR_NONE;
+  case XML_TOK_INVALID:
+    *eventPP = next;
+    return XML_ERROR_INVALID_TOKEN;
+  case XML_TOK_PARTIAL_CHAR:
+    if (nextPtr) {
+      *nextPtr = s;
+      return XML_ERROR_NONE;
+    }
+    return XML_ERROR_PARTIAL_CHAR;
+  case XML_TOK_PARTIAL:
+  case XML_TOK_NONE:
+    if (nextPtr) {
+      *nextPtr = s;
+      return XML_ERROR_NONE;
+    }
+    return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
+  default:
+    abort();
+  }
+  /* not reached */
+}
+
+#endif /* XML_DTD */
+
+static enum XML_Error
+initializeEncoding(XML_Parser parser)
+{
+  const char *s;
+#ifdef XML_UNICODE
+  char encodingBuf[128];
+  if (!protocolEncodingName)
+    s = 0;
+  else {
+    int i;
+    for (i = 0; protocolEncodingName[i]; i++) {
+      if (i == sizeof(encodingBuf) - 1
+          || (protocolEncodingName[i] & ~0x7f) != 0) {
+        encodingBuf[0] = '\0';
+        break;
+      }
+      encodingBuf[i] = (char)protocolEncodingName[i];
+    }
+    encodingBuf[i] = '\0';
+    s = encodingBuf;
+  }
+#else
+  s = protocolEncodingName;
+#endif
+  if ((ns ? XmlInitEncodingNS : xmlrpc_XmlInitEncoding)(&initEncoding, &encoding, s))
+    return XML_ERROR_NONE;
+  return handleUnknownEncoding(parser, protocolEncodingName);
+}
+
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+               const char *s, const char *next)
+{
+  const char *encodingName = 0;
+  const ENCODING *newEncoding = 0;
+  const char *version;
+  int standalone = -1;
+  if (!(ns
+        ? XmlParseXmlDeclNS
+        : xmlrpc_XmlParseXmlDecl)(isGeneralTextEntity,
+                           encoding,
+                           s,
+                           next,
+                           &eventPtr,
+                           &version,
+                           &encodingName,
+                           &newEncoding,
+                           &standalone))
+    return XML_ERROR_SYNTAX;
+  if (!isGeneralTextEntity && standalone == 1) {
+    dtd.standalone = 1;
+#ifdef XML_DTD
+    if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
+      paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif /* XML_DTD */
+  }
+  if (defaultHandler)
+    reportDefault(parser, encoding, s, next);
+  if (!protocolEncodingName) {
+    if (newEncoding) {
+      if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
+        eventPtr = encodingName;
+        return XML_ERROR_INCORRECT_ENCODING;
+      }
+      encoding = newEncoding;
+    }
+    else if (encodingName) {
+      enum XML_Error result;
+      const XML_Char * s =
+          poolStoreString(&tempPool,
+                          encoding,
+                          encodingName,
+                          encodingName
+                              + XmlNameLength(encoding, encodingName));
+      if (!s)
+        return XML_ERROR_NO_MEMORY;
+      result = handleUnknownEncoding(parser, s);
+      poolDiscard(&tempPool);
+      if (result == XML_ERROR_UNKNOWN_ENCODING)
+        eventPtr = encodingName;
+      return result;
+    }
+  }
+  return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+  if (unknownEncodingHandler) {
+    XML_Encoding info;
+    int i;
+    for (i = 0; i < 256; i++)
+      info.map[i] = -1;
+    info.convert = 0;
+    info.data = 0;
+    info.release = 0;
+    if (unknownEncodingHandler(unknownEncodingHandlerData,
+                               encodingName, &info)) {
+      ENCODING *enc;
+      unknownEncodingMem = malloc(xmlrpc_XmlSizeOfUnknownEncoding());
+      if (!unknownEncodingMem) {
+        if (info.release)
+          info.release(info.data);
+        return XML_ERROR_NO_MEMORY;
+      }
+      enc = (ns
+             ? XmlInitUnknownEncodingNS
+             : xmlrpc_XmlInitUnknownEncoding)(unknownEncodingMem,
+                                       info.map,
+                                       info.convert,
+                                       info.data);
+      if (enc) {
+        unknownEncodingData = info.data;
+        unknownEncodingRelease = info.release;
+        encoding = enc;
+        return XML_ERROR_NONE;
+      }
+    }
+    if (info.release)
+      info.release(info.data);
+  }
+  return XML_ERROR_UNKNOWN_ENCODING;
+}
+
+static enum XML_Error
+prologInitProcessor(XML_Parser parser,
+                    const char *s,
+                    const char *end,
+                    const char **nextPtr)
+{
+  enum XML_Error result = initializeEncoding(parser);
+  if (result != XML_ERROR_NONE)
+    return result;
+  processor = prologProcessor;
+  return prologProcessor(parser, s, end, nextPtr);
+}
+
+static enum XML_Error
+prologProcessor(XML_Parser parser,
+                const char *s,
+                const char *end,
+                const char **nextPtr)
+{
+  const char *next;
+  int tok = XmlPrologTok(encoding, s, end, &next);
+  return doProlog(parser, encoding, s, end, tok, next, nextPtr);
+}
+
+static enum XML_Error
+doProlog(XML_Parser parser,
+         const ENCODING *enc,
+         const char *s,
+         const char *end,
+         int tok,
+         const char *next,
+         const char **nextPtr)
+{
+#ifdef XML_DTD
+  static const XML_Char externalSubsetName[] = { '#' , '\0' };
+#endif /* XML_DTD */
+
+  const char **eventPP;
+  const char **eventEndPP;
+  if (enc == encoding) {
+    eventPP = &eventPtr;
+    eventEndPP = &eventEndPtr;
+  }
+  else {
+    eventPP = &(openInternalEntities->internalEventPtr);
+    eventEndPP = &(openInternalEntities->internalEventEndPtr);
+  }
+  for (;;) {
+    int role;
+    *eventPP = s;
+    *eventEndPP = next;
+    if (tok <= 0) {
+      if (nextPtr != 0 && tok != XML_TOK_INVALID) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      switch (tok) {
+      case XML_TOK_INVALID:
+        *eventPP = next;
+        return XML_ERROR_INVALID_TOKEN;
+      case XML_TOK_PARTIAL:
+        return XML_ERROR_UNCLOSED_TOKEN;
+      case XML_TOK_PARTIAL_CHAR:
+        return XML_ERROR_PARTIAL_CHAR;
+      case XML_TOK_NONE:
+#ifdef XML_DTD
+        if (enc != encoding)
+          return XML_ERROR_NONE;
+        if (parentParser) {
+          if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
+              == XML_ROLE_ERROR)
+            return XML_ERROR_SYNTAX;
+          hadExternalDoctype = 0;
+          return XML_ERROR_NONE;
+        }
+#endif /* XML_DTD */
+        return XML_ERROR_NO_ELEMENTS;
+      default:
+        tok = -tok;
+        next = end;
+        break;
+      }
+    }
+    role = XmlTokenRole(&prologState, tok, s, next, enc);
+    switch (role) {
+    case XML_ROLE_XML_DECL:
+      {
+        enum XML_Error result = processXmlDecl(parser, 0, s, next);
+        if (result != XML_ERROR_NONE)
+          return result;
+        enc = encoding;
+      }
+      break;
+    case XML_ROLE_DOCTYPE_NAME:
+      if (startDoctypeDeclHandler) {
+        const XML_Char *name = poolStoreString(&tempPool, enc, s, next);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        startDoctypeDeclHandler(handlerArg, name);
+        poolClear(&tempPool);
+      }
+      break;
+#ifdef XML_DTD
+    case XML_ROLE_TEXT_DECL:
+      {
+        enum XML_Error result = processXmlDecl(parser, 1, s, next);
+        if (result != XML_ERROR_NONE)
+          return result;
+        enc = encoding;
+      }
+      break;
+#endif /* XML_DTD */
+    case XML_ROLE_DOCTYPE_PUBLIC_ID:
+#ifdef XML_DTD
+      declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+                                    externalSubsetName,
+                                    sizeof(ENTITY));
+      if (!declEntity)
+        return XML_ERROR_NO_MEMORY;
+#endif /* XML_DTD */
+      /* fall through */
+    case XML_ROLE_ENTITY_PUBLIC_ID:
+      if (!XmlIsPublicId(enc, s, next, eventPP))
+        return XML_ERROR_SYNTAX;
+      if (declEntity) {
+        XML_Char *tem = poolStoreString(&dtd.pool,
+                                        enc,
+                                        s + enc->minBytesPerChar,
+                                        next - enc->minBytesPerChar);
+        if (!tem)
+          return XML_ERROR_NO_MEMORY;
+        normalizePublicId(tem);
+        declEntity->publicId = tem;
+        poolFinish(&dtd.pool);
+      }
+      break;
+    case XML_ROLE_DOCTYPE_CLOSE:
+      if (dtd.complete && hadExternalDoctype) {
+        dtd.complete = 0;
+#ifdef XML_DTD
+        if (paramEntityParsing && externalEntityRefHandler) {
+          ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities,
+                                            externalSubsetName,
+                                            0);
+          if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+                                        0,
+                                        entity->base,
+                                        entity->systemId,
+                                        entity->publicId))
+           return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+        }
+#endif /* XML_DTD */
+        if (!dtd.complete
+            && !dtd.standalone
+            && notStandaloneHandler
+            && !notStandaloneHandler(handlerArg))
+          return XML_ERROR_NOT_STANDALONE;
+      }
+      if (endDoctypeDeclHandler)
+        endDoctypeDeclHandler(handlerArg);
+      break;
+    case XML_ROLE_INSTANCE_START:
+      processor = contentProcessor;
+      return contentProcessor(parser, s, end, nextPtr);
+    case XML_ROLE_ATTLIST_ELEMENT_NAME:
+      {
+        const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        declElementType = (ELEMENT_TYPE *)
+            lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
+        if (!declElementType)
+          return XML_ERROR_NO_MEMORY;
+        if (declElementType->name != name)
+          poolDiscard(&dtd.pool);
+        else {
+          poolFinish(&dtd.pool);
+          if (!setElementTypePrefix(parser, declElementType))
+            return XML_ERROR_NO_MEMORY;
+        }
+        break;
+      }
+    case XML_ROLE_ATTRIBUTE_NAME:
+      declAttributeId = getAttributeId(parser, enc, s, next);
+      if (!declAttributeId)
+        return XML_ERROR_NO_MEMORY;
+      declAttributeIsCdata = 0;
+      declAttributeIsId = 0;
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
+      declAttributeIsCdata = 1;
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_ID:
+      declAttributeIsId = 1;
+      break;
+    case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
+    case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
+      if (dtd.complete
+          && !defineAttribute(declElementType, declAttributeId,
+                              declAttributeIsCdata,
+                              declAttributeIsId, 0))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
+    case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
+      {
+        const XML_Char *attVal;
+        enum XML_Error result
+          = storeAttributeValue(parser, enc, declAttributeIsCdata,
+                                s + enc->minBytesPerChar,
+                                next - enc->minBytesPerChar,
+                                &dtd.pool);
+        if (result)
+          return result;
+        attVal = poolStart(&dtd.pool);
+        poolFinish(&dtd.pool);
+        if (dtd.complete
+            /* ID attributes aren't allowed to have a default */
+            && !defineAttribute(declElementType, declAttributeId,
+                                declAttributeIsCdata, 0, attVal))
+          return XML_ERROR_NO_MEMORY;
+        break;
+      }
+    case XML_ROLE_ENTITY_VALUE:
+      {
+        enum XML_Error result = storeEntityValue(parser, enc,
+                                                 s + enc->minBytesPerChar,
+                                                 next - enc->minBytesPerChar);
+        if (declEntity) {
+          declEntity->textPtr = poolStart(&dtd.pool);
+          declEntity->textLen = poolLength(&dtd.pool);
+          poolFinish(&dtd.pool);
+          if (internalParsedEntityDeclHandler
+              /* Check it's not a parameter entity */
+              && ((ENTITY *)lookup(&dtd.generalEntities, declEntity->name, 0)
+                  == declEntity)) {
+            *eventEndPP = s;
+            internalParsedEntityDeclHandler(handlerArg,
+                                            declEntity->name,
+                                            declEntity->textPtr,
+                                            declEntity->textLen);
+          }
+        }
+        else
+          poolDiscard(&dtd.pool);
+        if (result != XML_ERROR_NONE)
+          return result;
+      }
+      break;
+    case XML_ROLE_DOCTYPE_SYSTEM_ID:
+      if (!dtd.standalone
+#ifdef XML_DTD
+          && !paramEntityParsing
+#endif /* XML_DTD */
+          && notStandaloneHandler
+          && !notStandaloneHandler(handlerArg))
+        return XML_ERROR_NOT_STANDALONE;
+      hadExternalDoctype = 1;
+#ifndef XML_DTD
+      break;
+#else /* XML_DTD */
+      if (!declEntity) {
+        declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+                                      externalSubsetName,
+                                      sizeof(ENTITY));
+        if (!declEntity)
+          return XML_ERROR_NO_MEMORY;
+      }
+      /* fall through */
+#endif /* XML_DTD */
+    case XML_ROLE_ENTITY_SYSTEM_ID:
+      if (declEntity) {
+        declEntity->systemId = poolStoreString(&dtd.pool, enc,
+                                               s + enc->minBytesPerChar,
+                                               next - enc->minBytesPerChar);
+        if (!declEntity->systemId)
+          return XML_ERROR_NO_MEMORY;
+        declEntity->base = curBase;
+        poolFinish(&dtd.pool);
+      }
+      break;
+    case XML_ROLE_ENTITY_NOTATION_NAME:
+      if (declEntity) {
+        declEntity->notation = poolStoreString(&dtd.pool, enc, s, next);
+        if (!declEntity->notation)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&dtd.pool);
+        if (unparsedEntityDeclHandler) {
+          *eventEndPP = s;
+          unparsedEntityDeclHandler(handlerArg,
+                                    declEntity->name,
+                                    declEntity->base,
+                                    declEntity->systemId,
+                                    declEntity->publicId,
+                                    declEntity->notation);
+        }
+
+      }
+      break;
+    case XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION:
+      if (declEntity && externalParsedEntityDeclHandler) {
+        *eventEndPP = s;
+        externalParsedEntityDeclHandler(handlerArg,
+                                        declEntity->name,
+                                        declEntity->base,
+                                        declEntity->systemId,
+                                        declEntity->publicId);
+      }
+      break;
+    case XML_ROLE_GENERAL_ENTITY_NAME:
+      {
+        const XML_Char *name;
+        if (XmlPredefinedEntityName(enc, s, next)) {
+          declEntity = 0;
+          break;
+        }
+        name = poolStoreString(&dtd.pool, enc, s, next);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        if (dtd.complete) {
+            declEntity = (ENTITY *)
+                lookup(&dtd.generalEntities, name, sizeof(ENTITY));
+          if (!declEntity)
+            return XML_ERROR_NO_MEMORY;
+          if (declEntity->name != name) {
+            poolDiscard(&dtd.pool);
+            declEntity = 0;
+          }
+          else
+            poolFinish(&dtd.pool);
+        }
+        else {
+          poolDiscard(&dtd.pool);
+          declEntity = 0;
+        }
+      }
+      break;
+    case XML_ROLE_PARAM_ENTITY_NAME:
+#ifdef XML_DTD
+      if (dtd.complete) {
+        const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        declEntity = (ENTITY *)
+            lookup(&dtd.paramEntities, name, sizeof(ENTITY));
+        if (!declEntity)
+          return XML_ERROR_NO_MEMORY;
+        if (declEntity->name != name) {
+          poolDiscard(&dtd.pool);
+          declEntity = 0;
+        }
+        else
+          poolFinish(&dtd.pool);
+      }
+#else /* not XML_DTD */
+      declEntity = 0;
+#endif /* not XML_DTD */
+      break;
+    case XML_ROLE_NOTATION_NAME:
+      declNotationPublicId = 0;
+      declNotationName = 0;
+      if (notationDeclHandler) {
+        declNotationName = poolStoreString(&tempPool, enc, s, next);
+        if (!declNotationName)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&tempPool);
+      }
+      break;
+    case XML_ROLE_NOTATION_PUBLIC_ID:
+      if (!XmlIsPublicId(enc, s, next, eventPP))
+        return XML_ERROR_SYNTAX;
+      if (declNotationName) {
+        XML_Char *tem = poolStoreString(&tempPool,
+                                        enc,
+                                        s + enc->minBytesPerChar,
+                                        next - enc->minBytesPerChar);
+        if (!tem)
+          return XML_ERROR_NO_MEMORY;
+        normalizePublicId(tem);
+        declNotationPublicId = tem;
+        poolFinish(&tempPool);
+      }
+      break;
+    case XML_ROLE_NOTATION_SYSTEM_ID:
+      if (declNotationName && notationDeclHandler) {
+        const XML_Char *systemId
+          = poolStoreString(&tempPool, enc,
+                            s + enc->minBytesPerChar,
+                            next - enc->minBytesPerChar);
+        if (!systemId)
+          return XML_ERROR_NO_MEMORY;
+        *eventEndPP = s;
+        notationDeclHandler(handlerArg,
+                            declNotationName,
+                            curBase,
+                            systemId,
+                            declNotationPublicId);
+      }
+      poolClear(&tempPool);
+      break;
+    case XML_ROLE_NOTATION_NO_SYSTEM_ID:
+      if (declNotationPublicId && notationDeclHandler) {
+        *eventEndPP = s;
+        notationDeclHandler(handlerArg,
+                            declNotationName,
+                            curBase,
+                            0,
+                            declNotationPublicId);
+      }
+      poolClear(&tempPool);
+      break;
+    case XML_ROLE_ERROR:
+      switch (tok) {
+      case XML_TOK_PARAM_ENTITY_REF:
+        return XML_ERROR_PARAM_ENTITY_REF;
+      case XML_TOK_XML_DECL:
+        return XML_ERROR_MISPLACED_XML_PI;
+      default:
+        return XML_ERROR_SYNTAX;
+      }
+#ifdef XML_DTD
+    case XML_ROLE_IGNORE_SECT:
+      {
+        enum XML_Error result;
+        if (defaultHandler)
+          reportDefault(parser, enc, s, next);
+        result = doIgnoreSection(parser, enc, &next, end, nextPtr);
+        if (!next) {
+          processor = ignoreSectionProcessor;
+          return result;
+        }
+      }
+      break;
+#endif /* XML_DTD */
+    case XML_ROLE_GROUP_OPEN:
+      if (prologState.level >= groupSize) {
+        if (groupSize)
+          groupConnector = realloc(groupConnector, groupSize *= 2);
+        else
+          groupConnector = malloc(groupSize = 32);
+        if (!groupConnector)
+          return XML_ERROR_NO_MEMORY;
+      }
+      groupConnector[prologState.level] = 0;
+      break;
+    case XML_ROLE_GROUP_SEQUENCE:
+      if (groupConnector[prologState.level] == '|')
+        return XML_ERROR_SYNTAX;
+      groupConnector[prologState.level] = ',';
+      break;
+    case XML_ROLE_GROUP_CHOICE:
+      if (groupConnector[prologState.level] == ',')
+        return XML_ERROR_SYNTAX;
+      groupConnector[prologState.level] = '|';
+      break;
+    case XML_ROLE_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+    case XML_ROLE_INNER_PARAM_ENTITY_REF:
+      if (paramEntityParsing
+          && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) {
+        const XML_Char *name;
+        ENTITY *entity;
+        name = poolStoreString(&dtd.pool, enc,
+                                s + enc->minBytesPerChar,
+                                next - enc->minBytesPerChar);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+        poolDiscard(&dtd.pool);
+        if (!entity) {
+          /* FIXME what to do if !dtd.complete? */
+          return XML_ERROR_UNDEFINED_ENTITY;
+        }
+        if (entity->open)
+          return XML_ERROR_RECURSIVE_ENTITY_REF;
+        if (entity->textPtr) {
+          enum XML_Error result;
+          result = processInternalParamEntity(parser, entity);
+          if (result != XML_ERROR_NONE)
+            return result;
+          break;
+        }
+        if (role == XML_ROLE_INNER_PARAM_ENTITY_REF)
+          return XML_ERROR_PARAM_ENTITY_REF;
+        if (externalEntityRefHandler) {
+          dtd.complete = 0;
+          entity->open = 1;
+          if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+                                        0,
+                                        entity->base,
+                                        entity->systemId,
+                                        entity->publicId)) {
+            entity->open = 0;
+            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+          }
+          entity->open = 0;
+          if (dtd.complete)
+            break;
+        }
+      }
+#endif /* XML_DTD */
+      if (!dtd.standalone
+          && notStandaloneHandler
+          && !notStandaloneHandler(handlerArg))
+        return XML_ERROR_NOT_STANDALONE;
+      dtd.complete = 0;
+      if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_ROLE_NONE:
+      switch (tok) {
+      case XML_TOK_PI:
+        if (!reportProcessingInstruction(parser, enc, s, next))
+          return XML_ERROR_NO_MEMORY;
+        break;
+      case XML_TOK_COMMENT:
+        if (!reportComment(parser, enc, s, next))
+          return XML_ERROR_NO_MEMORY;
+        break;
+      }
+      break;
+    }
+    if (defaultHandler) {
+      switch (tok) {
+      case XML_TOK_PI:
+      case XML_TOK_COMMENT:
+      case XML_TOK_BOM:
+      case XML_TOK_XML_DECL:
+#ifdef XML_DTD
+      case XML_TOK_IGNORE_SECT:
+#endif /* XML_DTD */
+      case XML_TOK_PARAM_ENTITY_REF:
+        break;
+      default:
+#ifdef XML_DTD
+        if (role != XML_ROLE_IGNORE_SECT)
+#endif /* XML_DTD */
+          reportDefault(parser, enc, s, next);
+      }
+    }
+    s = next;
+    tok = XmlPrologTok(enc, s, end, &next);
+  }
+  /* not reached */
+}
+
+static
+enum XML_Error epilogProcessor(XML_Parser parser,
+                               const char *s,
+                               const char *end,
+                               const char **nextPtr)
+{
+  processor = epilogProcessor;
+  eventPtr = s;
+  for (;;) {
+    const char *next;
+    int tok = XmlPrologTok(encoding, s, end, &next);
+    eventEndPtr = next;
+    switch (tok) {
+    case -XML_TOK_PROLOG_S:
+      if (defaultHandler) {
+        eventEndPtr = end;
+        reportDefault(parser, encoding, s, end);
+      }
+      /* fall through */
+    case XML_TOK_NONE:
+      if (nextPtr)
+        *nextPtr = end;
+      return XML_ERROR_NONE;
+    case XML_TOK_PROLOG_S:
+      if (defaultHandler)
+        reportDefault(parser, encoding, s, next);
+      break;
+    case XML_TOK_PI:
+      if (!reportProcessingInstruction(parser, encoding, s, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_COMMENT:
+      if (!reportComment(parser, encoding, s, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_INVALID:
+      eventPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_UNCLOSED_TOKEN;
+    case XML_TOK_PARTIAL_CHAR:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_PARTIAL_CHAR;
+    default:
+      return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+    }
+    eventPtr = s = next;
+  }
+}
+
+#ifdef XML_DTD
+
+static enum XML_Error
+processInternalParamEntity(XML_Parser parser, ENTITY *entity)
+{
+  const char *s, *end, *next;
+  int tok;
+  enum XML_Error result;
+  OPEN_INTERNAL_ENTITY openEntity;
+  entity->open = 1;
+  openEntity.next = openInternalEntities;
+  openInternalEntities = &openEntity;
+  openEntity.entity = entity;
+  openEntity.internalEventPtr = 0;
+  openEntity.internalEventEndPtr = 0;
+  s = (char *)entity->textPtr;
+  end = (char *)(entity->textPtr + entity->textLen);
+  tok = XmlPrologTok(internalEncoding, s, end, &next);
+  result = doProlog(parser, internalEncoding, s, end, tok, next, 0);
+  entity->open = 0;
+  openInternalEntities = openEntity.next;
+  return result;
+}
+
+#endif /* XML_DTD */
+
+
+
+static enum XML_Error
+errorProcessor(XML_Parser    const parser  ATTR_UNUSED,
+               const char *  const s       ATTR_UNUSED,
+               const char *  const end     ATTR_UNUSED,
+               const char ** const nextPtr ATTR_UNUSED) {
+
+    return errorCode;
+}
+
+
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+                    const char *ptr, const char *end,
+                    STRING_POOL *pool)
+{
+  enum XML_Error result =
+      appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
+  if (result)
+    return result;
+  if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+    poolChop(pool);
+  if (!poolAppendChar(pool, XML_T('\0')))
+    return XML_ERROR_NO_MEMORY;
+  return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+                     const char *ptr, const char *end,
+                     STRING_POOL *pool)
+{
+  for (;;) {
+    const char *next;
+    int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+    switch (tok) {
+    case XML_TOK_NONE:
+      return XML_ERROR_NONE;
+    case XML_TOK_INVALID:
+      if (enc == encoding)
+        eventPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      if (enc == encoding)
+        eventPtr = ptr;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_CHAR_REF:
+      {
+        XML_Char buf[XML_ENCODE_MAX];
+        int i;
+        int n = XmlCharRefNumber(enc, ptr);
+        if (n < 0) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_BAD_CHAR_REF;
+        }
+        if (!isCdata
+            && n == 0x20 /* space */
+            && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+          break;
+        n = XmlEncode(n, (ICHAR *)buf);
+        if (!n) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_BAD_CHAR_REF;
+        }
+        for (i = 0; i < n; i++) {
+          if (!poolAppendChar(pool, buf[i]))
+            return XML_ERROR_NO_MEMORY;
+        }
+      }
+      break;
+    case XML_TOK_DATA_CHARS:
+      if (!poolAppend(pool, enc, ptr, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+      break;
+    case XML_TOK_TRAILING_CR:
+      next = ptr + enc->minBytesPerChar;
+      /* fall through */
+    case XML_TOK_ATTRIBUTE_VALUE_S:
+    case XML_TOK_DATA_NEWLINE:
+      if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+        break;
+      if (!poolAppendChar(pool, 0x20))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_ENTITY_REF:
+      {
+        const XML_Char *name;
+        ENTITY *entity;
+        XML_Char ch = XmlPredefinedEntityName(enc,
+                                              ptr + enc->minBytesPerChar,
+                                              next - enc->minBytesPerChar);
+        if (ch) {
+          if (!poolAppendChar(pool, ch))
+            return XML_ERROR_NO_MEMORY;
+          break;
+        }
+        name = poolStoreString(&temp2Pool, enc,
+                               ptr + enc->minBytesPerChar,
+                               next - enc->minBytesPerChar);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+        poolDiscard(&temp2Pool);
+        if (!entity) {
+          if (dtd.complete) {
+            if (enc == encoding)
+              eventPtr = ptr;
+            return XML_ERROR_UNDEFINED_ENTITY;
+          }
+        }
+        else if (entity->open) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_RECURSIVE_ENTITY_REF;
+        }
+        else if (entity->notation) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_BINARY_ENTITY_REF;
+        }
+        else if (!entity->textPtr) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+        }
+        else {
+          enum XML_Error result;
+          const XML_Char *textEnd = entity->textPtr + entity->textLen;
+          entity->open = 1;
+          result = appendAttributeValue(parser, internalEncoding,
+                                        isCdata, (char *)entity->textPtr,
+                                        (char *)textEnd, pool);
+          entity->open = 0;
+          if (result)
+            return result;
+        }
+      }
+      break;
+    default:
+      abort();
+    }
+    ptr = next;
+  }
+  /* not reached */
+}
+
+static
+enum XML_Error storeEntityValue(XML_Parser parser,
+                                const ENCODING *enc,
+                                const char *entityTextPtr,
+                                const char *entityTextEnd)
+{
+  STRING_POOL *pool = &(dtd.pool);
+  for (;;) {
+    const char *next;
+    int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
+    switch (tok) {
+    case XML_TOK_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+      if (parentParser || enc != encoding) {
+        enum XML_Error result;
+        const XML_Char *name;
+        ENTITY *entity;
+        name = poolStoreString(&tempPool, enc,
+                               entityTextPtr + enc->minBytesPerChar,
+                               next - enc->minBytesPerChar);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+        poolDiscard(&tempPool);
+        if (!entity) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_UNDEFINED_ENTITY;
+        }
+        if (entity->open) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_RECURSIVE_ENTITY_REF;
+        }
+        if (entity->systemId) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_PARAM_ENTITY_REF;
+        }
+        entity->open = 1;
+        result = storeEntityValue(parser,
+                                  internalEncoding,
+                                  (char *)entity->textPtr,
+                                  (char *)(entity->textPtr + entity->textLen));
+        entity->open = 0;
+        if (result)
+          return result;
+        break;
+      }
+#endif /* XML_DTD */
+      eventPtr = entityTextPtr;
+      return XML_ERROR_SYNTAX;
+    case XML_TOK_NONE:
+      return XML_ERROR_NONE;
+    case XML_TOK_ENTITY_REF:
+    case XML_TOK_DATA_CHARS:
+      if (!poolAppend(pool, enc, entityTextPtr, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_TRAILING_CR:
+      next = entityTextPtr + enc->minBytesPerChar;
+      /* fall through */
+    case XML_TOK_DATA_NEWLINE:
+      if (pool->end == pool->ptr && !poolGrow(pool))
+        return XML_ERROR_NO_MEMORY;
+      *(pool->ptr)++ = 0xA;
+      break;
+    case XML_TOK_CHAR_REF:
+      {
+        XML_Char buf[XML_ENCODE_MAX];
+        int i;
+        int n = XmlCharRefNumber(enc, entityTextPtr);
+        if (n < 0) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_BAD_CHAR_REF;
+        }
+        n = XmlEncode(n, (ICHAR *)buf);
+        if (!n) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_BAD_CHAR_REF;
+        }
+        for (i = 0; i < n; i++) {
+          if (pool->end == pool->ptr && !poolGrow(pool))
+            return XML_ERROR_NO_MEMORY;
+          *(pool->ptr)++ = buf[i];
+        }
+      }
+      break;
+    case XML_TOK_PARTIAL:
+      if (enc == encoding)
+        eventPtr = entityTextPtr;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_INVALID:
+      if (enc == encoding)
+        eventPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    default:
+      abort();
+    }
+    entityTextPtr = next;
+  }
+  /* not reached */
+}
+
+static void
+normalizeLines(XML_Char *s)
+{
+  XML_Char *p;
+  for (;; s++) {
+    if (*s == XML_T('\0'))
+      return;
+    if (*s == 0xD)
+      break;
+  }
+  p = s;
+  do {
+    if (*s == 0xD) {
+      *p++ = 0xA;
+      if (*++s == 0xA)
+        s++;
+    }
+    else
+      *p++ = *s++;
+  } while (*s);
+  *p = XML_T('\0');
+}
+
+static int
+reportProcessingInstruction(XML_Parser parser,
+                            const ENCODING *enc,
+                            const char *start,
+                            const char *end)
+{
+  const XML_Char *target;
+  XML_Char *data;
+  const char *tem;
+  if (!processingInstructionHandler) {
+    if (defaultHandler)
+      reportDefault(parser, enc, start, end);
+    return 1;
+  }
+  start += enc->minBytesPerChar * 2;
+  tem = start + XmlNameLength(enc, start);
+  target = poolStoreString(&tempPool, enc, start, tem);
+  if (!target)
+    return 0;
+  poolFinish(&tempPool);
+  data = poolStoreString(&tempPool, enc,
+                        XmlSkipS(enc, tem),
+                        end - enc->minBytesPerChar*2);
+  if (!data)
+    return 0;
+  normalizeLines(data);
+  processingInstructionHandler(handlerArg, target, data);
+  poolClear(&tempPool);
+  return 1;
+}
+
+static int
+reportComment(XML_Parser parser,
+              const ENCODING *enc,
+              const char *start,
+              const char *end)
+{
+  XML_Char *data;
+  if (!commentHandler) {
+    if (defaultHandler)
+      reportDefault(parser, enc, start, end);
+    return 1;
+  }
+  data = poolStoreString(&tempPool,
+                         enc,
+                         start + enc->minBytesPerChar * 4, 
+                         end - enc->minBytesPerChar * 3);
+  if (!data)
+    return 0;
+  normalizeLines(data);
+  commentHandler(handlerArg, data);
+  poolClear(&tempPool);
+  return 1;
+}
+
+static void
+reportDefault(XML_Parser parser,
+              const ENCODING *enc,
+              const char *s,
+              const char *end)
+{
+  if (MUST_CONVERT(enc, s)) {
+    const char **eventPP;
+    const char **eventEndPP;
+    if (enc == encoding) {
+      eventPP = &eventPtr;
+      eventEndPP = &eventEndPtr;
+    }
+    else {
+      eventPP = &(openInternalEntities->internalEventPtr);
+      eventEndPP = &(openInternalEntities->internalEventEndPtr);
+    }
+    do {
+      ICHAR *dataPtr = (ICHAR *)dataBuf;
+      XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+      *eventEndPP = s;
+      defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+      *eventPP = s;
+    } while (s != end);
+  }
+  else
+    defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
+}
+
+
+static int
+defineAttribute(ELEMENT_TYPE *type,
+                ATTRIBUTE_ID *attId,
+                int isCdata,
+                int isId,
+                const XML_Char *value)
+{
+  DEFAULT_ATTRIBUTE *att;
+  if (value || isId) {
+    /* The handling of default attributes gets messed up if we have
+       a default which duplicates a non-default. */
+    int i;
+    for (i = 0; i < type->nDefaultAtts; i++)
+      if (attId == type->defaultAtts[i].id)
+        return 1;
+    if (isId && !type->idAtt && !attId->xmlns)
+      type->idAtt = attId;
+  }
+  if (type->nDefaultAtts == type->allocDefaultAtts) {
+    if (type->allocDefaultAtts == 0) {
+      type->allocDefaultAtts = 8;
+      type->defaultAtts =
+          malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+    }
+    else {
+      type->allocDefaultAtts *= 2;
+      type->defaultAtts =
+          realloc(type->defaultAtts,
+                  type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+    }
+    if (!type->defaultAtts)
+      return 0;
+  }
+  att = type->defaultAtts + type->nDefaultAtts;
+  att->id = attId;
+  att->value = value;
+  att->isCdata = isCdata;
+  if (!isCdata)
+    attId->maybeTokenized = 1;
+  type->nDefaultAtts += 1;
+  return 1;
+}
+
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+  const XML_Char *name;
+  for (name = elementType->name; *name; name++) {
+    if (*name == XML_T(':')) {
+      PREFIX *prefix;
+      const XML_Char *s;
+      for (s = elementType->name; s != name; s++) {
+        if (!poolAppendChar(&dtd.pool, *s))
+          return 0;
+      }
+      if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+        return 0;
+      prefix = (PREFIX *)
+          lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+      if (!prefix)
+        return 0;
+      if (prefix->name == poolStart(&dtd.pool))
+        poolFinish(&dtd.pool);
+      else
+        poolDiscard(&dtd.pool);
+      elementType->prefix = prefix;
+
+    }
+  }
+  return 1;
+}
+
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser,
+               const ENCODING *enc,
+               const char *start,
+               const char *end)
+{
+  ATTRIBUTE_ID *id;
+  const XML_Char *name;
+  if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+    return 0;
+  name = poolStoreString(&dtd.pool, enc, start, end);
+  if (!name)
+    return 0;
+  ++name;
+  id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
+  if (!id)
+    return 0;
+  if (id->name != name)
+    poolDiscard(&dtd.pool);
+  else {
+    poolFinish(&dtd.pool);
+    if (!ns)
+      ;
+    else if (name[0] == 'x'
+        && name[1] == 'm'
+        && name[2] == 'l'
+        && name[3] == 'n'
+        && name[4] == 's'
+        && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
+      if (name[5] == '\0')
+        id->prefix = &dtd.defaultPrefix;
+      else
+        id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
+      id->xmlns = 1;
+    }
+    else {
+      int i;
+      for (i = 0; name[i]; i++) {
+        if (name[i] == XML_T(':')) {
+          int j;
+          for (j = 0; j < i; j++) {
+            if (!poolAppendChar(&dtd.pool, name[j]))
+              return 0;
+          }
+          if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+            return 0;
+          id->prefix = (PREFIX *)
+              lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+          if (id->prefix->name == poolStart(&dtd.pool))
+            poolFinish(&dtd.pool);
+          else
+            poolDiscard(&dtd.pool);
+          break;
+        }
+      }
+    }
+  }
+  return id;
+}
+
+#define CONTEXT_SEP XML_T('\f')
+
+static
+const XML_Char *getContext(XML_Parser parser)
+{
+  HASH_TABLE_ITER iter;
+  int needSep = 0;
+
+  if (dtd.defaultPrefix.binding) {
+    int i;
+    int len;
+    if (!poolAppendChar(&tempPool, XML_T('=')))
+      return 0;
+    len = dtd.defaultPrefix.binding->uriLen;
+    if (namespaceSeparator != XML_T('\0'))
+      len--;
+    for (i = 0; i < len; i++)
+      if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
+        return 0;
+    needSep = 1;
+  }
+
+  hashTableIterInit(&iter, &(dtd.prefixes));
+  for (;;) {
+    int i;
+    int len;
+    const XML_Char *s;
+    PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+    if (!prefix)
+      break;
+    if (!prefix->binding)
+      continue;
+    if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+      return 0;
+    for (s = prefix->name; *s; s++)
+      if (!poolAppendChar(&tempPool, *s))
+        return 0;
+    if (!poolAppendChar(&tempPool, XML_T('=')))
+      return 0;
+    len = prefix->binding->uriLen;
+    if (namespaceSeparator != XML_T('\0'))
+      len--;
+    for (i = 0; i < len; i++)
+      if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+        return 0;
+    needSep = 1;
+  }
+
+
+  hashTableIterInit(&iter, &(dtd.generalEntities));
+  for (;;) {
+    const XML_Char *s;
+    ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
+    if (!e)
+      break;
+    if (!e->open)
+      continue;
+    if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+      return 0;
+    for (s = e->name; *s; s++)
+      if (!poolAppendChar(&tempPool, *s))
+        return 0;
+    needSep = 1;
+  }
+
+  if (!poolAppendChar(&tempPool, XML_T('\0')))
+    return 0;
+  return tempPool.start;
+}
+
+static
+int setContext(XML_Parser parser, const XML_Char *context)
+{
+  const XML_Char *s = context;
+
+  while (*context != XML_T('\0')) {
+    if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
+      ENTITY *e;
+      if (!poolAppendChar(&tempPool, XML_T('\0')))
+        return 0;
+      e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
+      if (e)
+        e->open = 1;
+      if (*s != XML_T('\0'))
+        s++;
+      context = s;
+      poolDiscard(&tempPool);
+    }
+    else if (*s == '=') {
+      PREFIX *prefix;
+      if (poolLength(&tempPool) == 0)
+        prefix = &dtd.defaultPrefix;
+      else {
+        if (!poolAppendChar(&tempPool, XML_T('\0')))
+          return 0;
+        prefix = (PREFIX *)
+            lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
+        if (!prefix)
+          return 0;
+        if (prefix->name == poolStart(&tempPool)) {
+          prefix->name = poolCopyString(&dtd.pool, prefix->name);
+          if (!prefix->name)
+            return 0;
+        }
+        poolDiscard(&tempPool);
+      }
+      for (context = s + 1;
+           *context != CONTEXT_SEP && *context != XML_T('\0');
+           ++context)
+        if (!poolAppendChar(&tempPool, *context))
+          return 0;
+      if (!poolAppendChar(&tempPool, XML_T('\0')))
+        return 0;
+      if (!addBinding(parser, prefix, 0, poolStart(&tempPool),
+                      &inheritedBindings))
+        return 0;
+      poolDiscard(&tempPool);
+      if (*context != XML_T('\0'))
+        ++context;
+      s = context;
+    }
+    else {
+      if (!poolAppendChar(&tempPool, *s))
+        return 0;
+      s++;
+    }
+  }
+  return 1;
+}
+
+
+static
+void normalizePublicId(XML_Char *publicId)
+{
+  XML_Char *p = publicId;
+  XML_Char *s;
+  for (s = publicId; *s; s++) {
+    switch (*s) {
+    case 0x20:
+    case 0xD:
+    case 0xA:
+      if (p != publicId && p[-1] != 0x20)
+        *p++ = 0x20;
+      break;
+    default:
+      *p++ = *s;
+    }
+  }
+  if (p != publicId && p[-1] == 0x20)
+    --p;
+  *p = XML_T('\0');
+}
+
+static int dtdInit(DTD *p)
+{
+  poolInit(&(p->pool));
+  hashTableInit(&(p->generalEntities));
+  hashTableInit(&(p->elementTypes));
+  hashTableInit(&(p->attributeIds));
+  hashTableInit(&(p->prefixes));
+  p->complete = 1;
+  p->standalone = 0;
+#ifdef XML_DTD
+  hashTableInit(&(p->paramEntities));
+#endif /* XML_DTD */
+  p->defaultPrefix.name = 0;
+  p->defaultPrefix.binding = 0;
+  return 1;
+}
+
+#ifdef XML_DTD
+
+static void dtdSwap(DTD *p1, DTD *p2)
+{
+  DTD tem;
+  memcpy(&tem, p1, sizeof(DTD));
+  memcpy(p1, p2, sizeof(DTD));
+  memcpy(p2, &tem, sizeof(DTD));
+}
+
+#endif /* XML_DTD */
+
+static void dtdDestroy(DTD *p)
+{
+  HASH_TABLE_ITER iter;
+  hashTableIterInit(&iter, &(p->elementTypes));
+  for (;;) {
+    ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+    if (!e)
+      break;
+    if (e->allocDefaultAtts != 0)
+      free(e->defaultAtts);
+  }
+  hashTableDestroy(&(p->generalEntities));
+#ifdef XML_DTD
+  hashTableDestroy(&(p->paramEntities));
+#endif /* XML_DTD */
+  hashTableDestroy(&(p->elementTypes));
+  hashTableDestroy(&(p->attributeIds));
+  hashTableDestroy(&(p->prefixes));
+  poolDestroy(&(p->pool));
+}
+
+/* Do a deep copy of the DTD.  Return 0 for out of memory; non-zero otherwise.
+The new DTD has already been initialized. */
+
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd)
+{
+  HASH_TABLE_ITER iter;
+
+  /* Copy the prefix table. */
+
+  hashTableIterInit(&iter, &(oldDtd->prefixes));
+  for (;;) {
+    const XML_Char *name;
+    const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+    if (!oldP)
+      break;
+    name = poolCopyString(&(newDtd->pool), oldP->name);
+    if (!name)
+      return 0;
+    if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
+      return 0;
+  }
+
+  hashTableIterInit(&iter, &(oldDtd->attributeIds));
+
+  /* Copy the attribute id table. */
+
+  for (;;) {
+    ATTRIBUTE_ID *newA;
+    const XML_Char *name;
+    const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
+
+    if (!oldA)
+      break;
+    /* Remember to allocate the scratch byte before the name. */
+    if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+      return 0;
+    name = poolCopyString(&(newDtd->pool), oldA->name);
+    if (!name)
+      return 0;
+    ++name;
+    newA = (ATTRIBUTE_ID *)
+        lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
+    if (!newA)
+      return 0;
+    newA->maybeTokenized = oldA->maybeTokenized;
+    if (oldA->prefix) {
+      newA->xmlns = oldA->xmlns;
+      if (oldA->prefix == &oldDtd->defaultPrefix)
+        newA->prefix = &newDtd->defaultPrefix;
+      else
+        newA->prefix = (PREFIX *)
+            lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
+    }
+  }
+
+  /* Copy the element type table. */
+
+  hashTableIterInit(&iter, &(oldDtd->elementTypes));
+
+  for (;;) {
+    int i;
+    ELEMENT_TYPE *newE;
+    const XML_Char *name;
+    const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+    if (!oldE)
+      break;
+    name = poolCopyString(&(newDtd->pool), oldE->name);
+    if (!name)
+      return 0;
+    newE = (ELEMENT_TYPE *)
+        lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
+    if (!newE)
+      return 0;
+    if (oldE->nDefaultAtts) {
+      newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
+          malloc(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+      if (!newE->defaultAtts)
+        return 0;
+    }
+    if (oldE->idAtt)
+      newE->idAtt = (ATTRIBUTE_ID *)
+          lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
+    newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+    if (oldE->prefix)
+      newE->prefix = (PREFIX *)
+          lookup(&(newDtd->prefixes), oldE->prefix->name, 0);
+    for (i = 0; i < newE->nDefaultAtts; i++) {
+      newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
+          lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+      newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+      if (oldE->defaultAtts[i].value) {
+        newE->defaultAtts[i].value =
+            poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
+        if (!newE->defaultAtts[i].value)
+          return 0;
+      }
+      else
+        newE->defaultAtts[i].value = 0;
+    }
+  }
+
+  /* Copy the entity tables. */
+  if (!copyEntityTable(&(newDtd->generalEntities),
+                       &(newDtd->pool),
+                       &(oldDtd->generalEntities)))
+      return 0;
+
+#ifdef XML_DTD
+  if (!copyEntityTable(&(newDtd->paramEntities),
+                       &(newDtd->pool),
+                       &(oldDtd->paramEntities)))
+      return 0;
+#endif /* XML_DTD */
+
+  newDtd->complete = oldDtd->complete;
+  newDtd->standalone = oldDtd->standalone;
+  return 1;
+}
+
+static int copyEntityTable(HASH_TABLE *newTable,
+                           STRING_POOL *newPool,
+                           const HASH_TABLE *oldTable)
+{
+  HASH_TABLE_ITER iter;
+  const XML_Char *cachedOldBase = 0;
+  const XML_Char *cachedNewBase = 0;
+
+  hashTableIterInit(&iter, oldTable);
+
+  for (;;) {
+    ENTITY *newE;
+    const XML_Char *name;
+    const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
+    if (!oldE)
+      break;
+    name = poolCopyString(newPool, oldE->name);
+    if (!name)
+      return 0;
+    newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
+    if (!newE)
+      return 0;
+    if (oldE->systemId) {
+      const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
+      if (!tem)
+        return 0;
+      newE->systemId = tem;
+      if (oldE->base) {
+        if (oldE->base == cachedOldBase)
+          newE->base = cachedNewBase;
+        else {
+          cachedOldBase = oldE->base;
+          tem = poolCopyString(newPool, cachedOldBase);
+          if (!tem)
+            return 0;
+          cachedNewBase = newE->base = tem;
+        }
+      }
+    }
+    else {
+      const XML_Char *tem =
+          poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
+      if (!tem)
+        return 0;
+      newE->textPtr = tem;
+      newE->textLen = oldE->textLen;
+    }
+    if (oldE->notation) {
+      const XML_Char *tem = poolCopyString(newPool, oldE->notation);
+      if (!tem)
+        return 0;
+      newE->notation = tem;
+    }
+  }
+  return 1;
+}
+
+#define INIT_SIZE 64
+
+static
+int keyeq(KEY s1, KEY s2)
+{
+  for (; *s1 == *s2; s1++, s2++)
+    if (*s1 == 0)
+      return 1;
+  return 0;
+}
+
+static
+unsigned long hash(KEY s)
+{
+  unsigned long h = 0;
+  while (*s)
+    h = (h << 5) + h + (unsigned char)*s++;
+  return h;
+}
+
+static
+NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
+{
+  size_t i;
+  if (table->size == 0) {
+    if (!createSize)
+      return 0;
+    table->v = calloc(INIT_SIZE, sizeof(NAMED *));
+    if (!table->v)
+      return 0;
+    table->size = INIT_SIZE;
+    table->usedLim = INIT_SIZE / 2;
+    i = hash(name) & (table->size - 1);
+  }
+  else {
+    unsigned long h = hash(name);
+    for (i = h & (table->size - 1);
+         table->v[i];
+         i == 0 ? i = table->size - 1 : --i) {
+      if (keyeq(name, table->v[i]->name))
+        return table->v[i];
+    }
+    if (!createSize)
+      return 0;
+    if (table->used == table->usedLim) {
+      /* check for overflow */
+      size_t newSize = table->size * 2;
+      NAMED **newV = calloc(newSize, sizeof(NAMED *));
+      if (!newV)
+        return 0;
+      for (i = 0; i < table->size; i++)
+        if (table->v[i]) {
+          size_t j;
+          for (j = hash(table->v[i]->name) & (newSize - 1);
+               newV[j];
+               j == 0 ? j = newSize - 1 : --j)
+            ;
+          newV[j] = table->v[i];
+        }
+      free(table->v);
+      table->v = newV;
+      table->size = newSize;
+      table->usedLim = newSize/2;
+      for (i = h & (table->size - 1);
+           table->v[i];
+           i == 0 ? i = table->size - 1 : --i)
+        ;
+    }
+  }
+  table->v[i] = calloc(1, createSize);
+  if (!table->v[i])
+    return 0;
+  table->v[i]->name = name;
+  (table->used)++;
+  return table->v[i];
+}
+
+static
+void hashTableDestroy(HASH_TABLE *table)
+{
+  size_t i;
+  for (i = 0; i < table->size; i++) {
+    NAMED *p = table->v[i];
+    if (p)
+      free(p);
+  }
+  if (table->v)
+    free(table->v);
+}
+
+static
+void hashTableInit(HASH_TABLE *p)
+{
+  p->size = 0;
+  p->usedLim = 0;
+  p->used = 0;
+  p->v = 0;
+}
+
+static
+void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
+{
+  iter->p = table->v;
+  iter->end = iter->p + table->size;
+}
+
+static
+NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
+{
+  while (iter->p != iter->end) {
+    NAMED *tem = *(iter->p)++;
+    if (tem)
+      return tem;
+  }
+  return 0;
+}
+
+
+static
+void poolInit(STRING_POOL *pool)
+{
+  pool->blocks = 0;
+  pool->freeBlocks = 0;
+  pool->start = 0;
+  pool->ptr = 0;
+  pool->end = 0;
+}
+
+static
+void poolClear(STRING_POOL *pool)
+{
+  if (!pool->freeBlocks)
+    pool->freeBlocks = pool->blocks;
+  else {
+    BLOCK *p = pool->blocks;
+    while (p) {
+      BLOCK *tem = p->next;
+      p->next = pool->freeBlocks;
+      pool->freeBlocks = p;
+      p = tem;
+    }
+  }
+  pool->blocks = 0;
+  pool->start = 0;
+  pool->ptr = 0;
+  pool->end = 0;
+}
+
+static
+void poolDestroy(STRING_POOL *pool)
+{
+  BLOCK *p = pool->blocks;
+  while (p) {
+    BLOCK *tem = p->next;
+    free(p);
+    p = tem;
+  }
+  pool->blocks = 0;
+  p = pool->freeBlocks;
+  while (p) {
+    BLOCK *tem = p->next;
+    free(p);
+    p = tem;
+  }
+  pool->freeBlocks = 0;
+  pool->ptr = 0;
+  pool->start = 0;
+  pool->end = 0;
+}
+
+static
+XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+                     const char *ptr, const char *end)
+{
+  if (!pool->ptr && !poolGrow(pool))
+    return 0;
+  for (;;) {
+    XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+    if (ptr == end)
+      break;
+    if (!poolGrow(pool))
+      return 0;
+  }
+  return pool->start;
+}
+
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
+{
+  do {
+    if (!poolAppendChar(pool, *s))
+      return 0;
+  } while (*s++);
+  s = pool->start;
+  poolFinish(pool);
+  return s;
+}
+
+static const XML_Char *
+poolCopyStringN(STRING_POOL *pool,
+                const XML_Char *s,
+                int n)
+{
+  if (!pool->ptr && !poolGrow(pool))
+    return 0;
+  for (; n > 0; --n, s++) {
+    if (!poolAppendChar(pool, *s))
+      return 0;
+
+  }
+  s = pool->start;
+  poolFinish(pool);
+  return s;
+}
+
+static
+XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+                          const char *ptr, const char *end)
+{
+  if (!poolAppend(pool, enc, ptr, end))
+    return 0;
+  if (pool->ptr == pool->end && !poolGrow(pool))
+    return 0;
+  *(pool->ptr)++ = 0;
+  return pool->start;
+}
+
+static
+int poolGrow(STRING_POOL *pool)
+{
+  if (pool->freeBlocks) {
+    if (pool->start == 0) {
+      pool->blocks = pool->freeBlocks;
+      pool->freeBlocks = pool->freeBlocks->next;
+      pool->blocks->next = 0;
+      pool->start = pool->blocks->s;
+      pool->end = pool->start + pool->blocks->size;
+      pool->ptr = pool->start;
+      return 1;
+    }
+    if (pool->end - pool->start < pool->freeBlocks->size) {
+      BLOCK *tem = pool->freeBlocks->next;
+      pool->freeBlocks->next = pool->blocks;
+      pool->blocks = pool->freeBlocks;
+      pool->freeBlocks = tem;
+      memcpy(pool->blocks->s, pool->start,
+             (pool->end - pool->start) * sizeof(XML_Char));
+      pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+      pool->start = pool->blocks->s;
+      pool->end = pool->start + pool->blocks->size;
+      return 1;
+    }
+  }
+  if (pool->blocks && pool->start == pool->blocks->s) {
+    int blockSize = (pool->end - pool->start)*2;
+    pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) +
+                           blockSize * sizeof(XML_Char));
+    if (!pool->blocks)
+      return 0;
+    pool->blocks->size = blockSize;
+    pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+    pool->start = pool->blocks->s;
+    pool->end = pool->start + blockSize;
+  }
+  else {
+    BLOCK *tem;
+    int blockSize = pool->end - pool->start;
+    if (blockSize < INIT_BLOCK_SIZE)
+      blockSize = INIT_BLOCK_SIZE;
+    else
+      blockSize *= 2;
+    tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+    if (!tem)
+      return 0;
+    tem->size = blockSize;
+    tem->next = pool->blocks;
+    pool->blocks = tem;
+    if (pool->ptr != pool->start)
+      memcpy(tem->s, pool->start,
+             (pool->ptr - pool->start) * sizeof(XML_Char));
+    pool->ptr = tem->s + (pool->ptr - pool->start);
+    pool->start = tem->s;
+    pool->end = tem->s + blockSize;
+  }
+  return 1;
+}
diff --git a/lib/expat/xmlparse/xmlparse.dsp b/lib/expat/xmlparse/xmlparse.dsp
new file mode 100644 (file)
index 0000000..b95795a
--- /dev/null
@@ -0,0 +1,279 @@
+# Microsoft Developer Studio Project File - Name="xmlparse" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmlparse - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlparse.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xmlparse.mak" CFG="xmlparse - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xmlparse - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmlparse - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmlparse - Win32 Release DLL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "xmlparse - Win32 Debug DLL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "xmlparse - Win32 MinSize DLL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "xmlparse"
+# PROP Scc_LocalPath ".."
+
+!IF  "$(CFG)" == "xmlparse - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmlparse"
+# PROP Intermediate_Dir "Release\xmlparse"
+# PROP Target_Dir "."
+LINK32=link.exe -lib
+MTL=midl.exe
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmlparse"
+# PROP Intermediate_Dir "Debug\xmlparse"
+# PROP Target_Dir "."
+LINK32=link.exe -lib
+MTL=midl.exe
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Release DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\ReleaseDLL"
+# PROP BASE Intermediate_Dir ".\ReleaseDLL"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseDLL\xmlparse"
+# PROP Intermediate_Dir "ReleaseDLL\xmlparse"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "XML_NS" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:I386 /link50compat
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Debug DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\DebugDLL"
+# PROP BASE Intermediate_Dir ".\DebugDLL"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugDLL\xmlparse"
+# PROP Intermediate_Dir "DebugDLL\xmlparse"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+CPP=cl.exe
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /debug /machine:I386
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 MinSize DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\ReleaseMinSizeDLL"
+# PROP BASE Intermediate_Dir ".\ReleaseMinSizeDLL"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseMinSizeDLL\xmlparse"
+# PROP Intermediate_Dir "ReleaseMinSizeDLL\xmlparse"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+CPP=cl.exe
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_NS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O1 /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "XML_MIN_SIZE" /D "XML_WINLIB" /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:I386
+# SUBTRACT BASE LINK32 /profile
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x20000000" /entry:"DllMain" /subsystem:windows /dll /machine:I386
+# SUBTRACT LINK32 /profile /nodefaultlib
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xmlparse - Win32 Release"
+# Name "xmlparse - Win32 Debug"
+# Name "xmlparse - Win32 Release DLL"
+# Name "xmlparse - Win32 Debug DLL"
+# Name "xmlparse - Win32 MinSize DLL"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=..\xmltok\dllmain.c
+
+!IF  "$(CFG)" == "xmlparse - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Release DLL"
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Debug DLL"
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 MinSize DLL"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\xmltok\xmlrole.c
+
+!IF  "$(CFG)" == "xmlparse - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Release DLL"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Debug DLL"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 MinSize DLL"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\xmltok\xmltok.c
+
+!IF  "$(CFG)" == "xmlparse - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Release DLL"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 Debug DLL"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmlparse - Win32 MinSize DLL"
+
+!ENDIF 
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\xmlparse.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/lib/expat/xmlparse/xmlparse.h b/lib/expat/xmlparse/xmlparse.h
new file mode 100644 (file)
index 0000000..7db48f4
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+  Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+  See the file copying.txt for copying permission.
+*/
+
+#ifndef XMLPARSE_H_INCLUDED
+#define XMLPARSE_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef XMLPARSEAPI
+#define XMLPARSEAPI /* as nothing */
+#endif
+
+typedef void *XML_Parser;
+
+#ifdef XML_UNICODE_WCHAR_T
+
+/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t
+   uses Unicode.
+*/
+/* Information is UTF-16 encoded as wchar_ts */
+
+#ifndef XML_UNICODE
+#define XML_UNICODE
+#endif
+
+#include <stddef.h>
+typedef wchar_t XML_Char;
+typedef wchar_t XML_LChar;
+
+#else /* not XML_UNICODE_WCHAR_T */
+
+#ifdef XML_UNICODE
+
+/* Information is UTF-16 encoded as unsigned shorts */
+typedef unsigned short XML_Char;
+typedef char XML_LChar;
+
+#else /* not XML_UNICODE */
+
+/* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+
+#endif /* not XML_UNICODE */
+
+#endif /* not XML_UNICODE_WCHAR_T */
+
+
+/* Constructs a new parser; encoding is the encoding specified by the external
+protocol or null if there is none specified. */
+
+XML_Parser XMLPARSEAPI
+xmlrpc_XML_ParserCreate(const XML_Char * encoding);
+
+/* Constructs a new parser and namespace processor.  Element type names
+and attribute names that belong to a namespace will be expanded;
+unprefixed attribute names are never expanded; unprefixed element type
+names are expanded only if there is a default namespace. The expanded
+name is the concatenation of the namespace URI, the namespace separator character,
+and the local part of the name.  If the namespace separator is '\0' then
+the namespace URI and the local part will be concatenated without any
+separator.  When a namespace is not declared, the name and prefix will be
+passed through without expansion. */
+
+XML_Parser XMLPARSEAPI
+xmlrpc_XML_ParserCreateNS(const XML_Char *encoding,
+                          XML_Char namespaceSeparator);
+
+
+/* atts is array of name/value pairs, terminated by 0;
+   names and values are 0 terminated. */
+
+typedef void (*XML_StartElementHandler)(void *userData,
+                    const XML_Char *name,
+                    const XML_Char **atts);
+
+typedef void (*XML_EndElementHandler)(void *userData,
+                      const XML_Char *name);
+
+/* s is not 0 terminated. */
+typedef void (*XML_CharacterDataHandler)(void *userData,
+                     const XML_Char *s,
+                     int len);
+
+/* target and data are 0 terminated */
+typedef void (*XML_ProcessingInstructionHandler)(void *userData,
+                         const XML_Char *target,
+                         const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data);
+
+typedef void (*XML_StartCdataSectionHandler)(void *userData);
+typedef void (*XML_EndCdataSectionHandler)(void *userData);
+
+/* This is called for any characters in the XML document for
+which there is no applicable handler.  This includes both
+characters that are part of markup which is of a kind that is
+not reported (comments, markup declarations), or characters
+that are part of a construct which could be reported but
+for which no handler has been supplied. The characters are passed
+exactly as they were in the XML document except that
+they will be encoded in UTF-8.  Line boundaries are not normalized.
+Note that a byte order mark character is not passed to the default handler.
+There are no guarantees about how characters are divided between calls
+to the default handler: for example, a comment might be split between
+multiple calls. */
+
+typedef void (*XML_DefaultHandler)(void *userData,
+                   const XML_Char *s,
+                   int len);
+
+/* This is called for the start of the DOCTYPE declaration when the
+name of the DOCTYPE is encountered. */
+typedef void (*XML_StartDoctypeDeclHandler)(void *userData,
+                        const XML_Char *doctypeName);
+
+/* This is called for the start of the DOCTYPE declaration when the
+closing > is encountered, but after processing any external subset. */
+typedef void (*XML_EndDoctypeDeclHandler)(void *userData);
+
+/* This is called for a declaration of an unparsed (NDATA)
+entity.  The base argument is whatever was set by XML_SetBase.
+The entityName, systemId and notationName arguments will never be null.
+The other arguments may be. */
+
+typedef void (*XML_UnparsedEntityDeclHandler)(void *userData,
+                          const XML_Char *entityName,
+                          const XML_Char *base,
+                          const XML_Char *systemId,
+                          const XML_Char *publicId,
+                          const XML_Char *notationName);
+
+/* This is called for a declaration of notation.
+The base argument is whatever was set by XML_SetBase.
+The notationName will never be null.  The other arguments can be. */
+
+typedef void (*XML_NotationDeclHandler)(void *userData,
+                    const XML_Char *notationName,
+                    const XML_Char *base,
+                    const XML_Char *systemId,
+                    const XML_Char *publicId);
+
+typedef void (*XML_ExternalParsedEntityDeclHandler)(void *userData,
+                            const XML_Char *entityName,
+                            const XML_Char *base,
+                            const XML_Char *systemId,
+                            const XML_Char *publicId);
+
+typedef void (*XML_InternalParsedEntityDeclHandler)(void *userData,
+                            const XML_Char *entityName,
+                            const XML_Char *replacementText,
+                            int replacementTextLength);
+
+/* When namespace processing is enabled, these are called once for
+each namespace declaration. The call to the start and end element
+handlers occur between the calls to the start and end namespace
+declaration handlers. For an xmlns attribute, prefix will be null.
+For an xmlns="" attribute, uri will be null. */
+
+typedef void (*XML_StartNamespaceDeclHandler)(void *userData,
+                          const XML_Char *prefix,
+                          const XML_Char *uri);
+
+typedef void (*XML_EndNamespaceDeclHandler)(void *userData,
+                        const XML_Char *prefix);
+
+/* This is called if the document is not standalone (it has an
+external subset or a reference to a parameter entity, but does not
+have standalone="yes"). If this handler returns 0, then processing
+will not continue, and the parser will return a
+XML_ERROR_NOT_STANDALONE error. */
+
+typedef int (*XML_NotStandaloneHandler)(void *userData);
+
+/* This is called for a reference to an external parsed general entity.
+The referenced entity is not automatically parsed.
+The application can parse it immediately or later using
+XML_ExternalEntityParserCreate.
+The parser argument is the parser parsing the entity containing the reference;
+it can be passed as the parser argument to XML_ExternalEntityParserCreate.
+The systemId argument is the system identifier as specified in the entity declaration;
+it will not be null.
+The base argument is the system identifier that should be used as the base for
+resolving systemId if systemId was relative; this is set by XML_SetBase;
+it may be null.
+The publicId argument is the public identifier as specified in the entity declaration,
+or null if none was specified; the whitespace in the public identifier
+will have been normalized as required by the XML spec.
+The context argument specifies the parsing context in the format
+expected by the context argument to
+XML_ExternalEntityParserCreate; context is valid only until the handler
+returns, so if the referenced entity is to be parsed later, it must be copied.
+The handler should return 0 if processing should not continue because of
+a fatal error in the handling of the external entity.
+In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING
+error.
+Note that unlike other handlers the first argument is the parser, not userData. */
+
+typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
+                        const XML_Char *context,
+                        const XML_Char *base,
+                        const XML_Char *systemId,
+                        const XML_Char *publicId);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler
+to provide information to the parser about encodings that are unknown
+to the parser.
+The map[b] member gives information about byte sequences
+whose first byte is b.
+If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c.
+If map[b] is -1, then the byte sequence is malformed.
+If map[b] is -n, where n >= 2, then b is the first byte of an n-byte
+sequence that encodes a single Unicode scalar value.
+The data member will be passed as the first argument to the convert function.
+The convert function is used to convert multibyte sequences;
+s will point to a n-byte sequence where map[(unsigned char)*s] == -n.
+The convert function must return the Unicode scalar value
+represented by this byte sequence or -1 if the byte sequence is malformed.
+The convert function may be null if the encoding is a single-byte encoding,
+that is if map[b] >= -1 for all bytes b.
+When the parser is finished with the encoding, then if release is not null,
+it will call release passing it the data member;
+once release has been called, the convert function will not be called again.
+
+Expat places certain restrictions on the encodings that are supported
+using this mechanism.
+
+1. Every ASCII character that can appear in a well-formed XML document,
+other than the characters
+
+  $@\^`{}~
+
+must be represented by a single byte, and that byte must be the
+same byte that represents that character in ASCII.
+
+2. No character may require more than 4 bytes to encode.
+
+3. All characters encoded must have Unicode scalar values <= 0xFFFF,
+(ie characters that would be encoded by surrogates in UTF-16
+are  not allowed).  Note that this restriction doesn't apply to
+the built-in support for UTF-8 and UTF-16.
+
+4. No Unicode character may be encoded by more than one distinct sequence
+of bytes. */
+
+typedef struct {
+  int map[256];
+  void *data;
+  int (*convert)(void *data, const char *s);
+  void (*release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+The encodingHandlerData argument is that which was passed as the
+second argument to XML_SetUnknownEncodingHandler.
+The name argument gives the name of the encoding as specified in
+the encoding declaration.
+If the callback can provide information about the encoding,
+it must fill in the XML_Encoding structure, and return 1.
+Otherwise it must return 0.
+If info does not describe a suitable encoding,
+then the parser will return an XML_UNKNOWN_ENCODING error. */
+
+typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData,
+                      const XML_Char *name,
+                      XML_Encoding *info);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetElementHandler(XML_Parser parser,
+                             XML_StartElementHandler start,
+                             XML_EndElementHandler end);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetCharacterDataHandler(XML_Parser parser,
+                                   XML_CharacterDataHandler handler);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetProcessingInstructionHandler(
+    XML_Parser parser,
+    XML_ProcessingInstructionHandler handler);
+void XMLPARSEAPI
+xmlrpc_XML_SetCommentHandler(XML_Parser parser,
+                             XML_CommentHandler handler);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetCdataSectionHandler(XML_Parser parser,
+                                  XML_StartCdataSectionHandler start,
+                                  XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of
+   internal entities.  The entity reference will be passed to the default
+   handler.
+*/
+
+void XMLPARSEAPI
+xmlrpc_XML_SetDefaultHandler(XML_Parser parser,
+                             XML_DefaultHandler handler);
+
+/* This sets the default handler but does not inhibit expansion of internal entities.
+The entity reference will not be passed to the default handler. */
+
+void XMLPARSEAPI
+xmlrpc_XML_SetDefaultHandlerExpand(XML_Parser parser,
+                                   XML_DefaultHandler handler);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetDoctypeDeclHandler(XML_Parser parser,
+                                 XML_StartDoctypeDeclHandler start,
+                                 XML_EndDoctypeDeclHandler end);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+                                        XML_UnparsedEntityDeclHandler handler);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetNotationDeclHandler(XML_Parser parser,
+                                  XML_NotationDeclHandler handler);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetExternalParsedEntityDeclHandler(
+    XML_Parser parser,
+    XML_ExternalParsedEntityDeclHandler handler);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetInternalParsedEntityDeclHandler(
+    XML_Parser parser,
+    XML_InternalParsedEntityDeclHandler handler);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetNamespaceDeclHandler(XML_Parser parser,
+                                   XML_StartNamespaceDeclHandler start,
+                                   XML_EndNamespaceDeclHandler end);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetNotStandaloneHandler(XML_Parser parser,
+                                   XML_NotStandaloneHandler handler);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetExternalEntityRefHandler(XML_Parser parser,
+                                       XML_ExternalEntityRefHandler handler);
+
+/* If a non-null value for arg is specified here, then it will be
+   passed as the first argument to the external entity ref handler
+   instead of the parser object.
+*/
+void XMLPARSEAPI
+xmlrpc_XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
+
+void XMLPARSEAPI
+xmlrpc_XML_SetUnknownEncodingHandler(XML_Parser parser,
+                                     XML_UnknownEncodingHandler handler,
+                                     void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end element,
+   processing instruction or character data.  It causes the corresponding
+   markup to be passed to the default handler.
+*/
+void XMLPARSEAPI
+xmlrpc_XML_DefaultCurrent(XML_Parser parser);
+
+/* This value is passed as the userData argument to callbacks. */
+void XMLPARSEAPI
+xmlrpc_XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or null. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument
+to XML_ParserCreate. It must not be called after XML_Parse
+or XML_ParseBuffer. */
+
+int XMLPARSEAPI
+xmlrpc_XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+
+/* If this function is called, then the parser will be passed
+   as the first argument to callbacks instead of userData.
+   The userData will still be accessible using XML_GetUserData.
+*/
+void XMLPARSEAPI
+xmlrpc_XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* Sets the base to be used for resolving relative URIs in system
+   identifiers in declarations.  Resolving relative identifiers is left
+   to the application: this value will be passed through as the base
+   argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler
+   and XML_UnparsedEntityDeclHandler. The base argument will be copied.
+   Returns zero if out of memory, non-zero otherwise.
+*/
+int XMLPARSEAPI
+xmlrpc_XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+const XML_Char XMLPARSEAPI *
+xmlrpc_XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attribute/value pairs passed in last call
+   to the XML_StartElementHandler that were specified in the start-tag
+   rather than defaulted. Each attribute/value pair counts as 2; thus
+   this correspondds to an index into the atts array passed to the
+   XML_StartElementHandler.
+*/
+int XMLPARSEAPI
+xmlrpc_XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Returns the index of the ID attribute passed in the last call to
+   XML_StartElementHandler, or -1 if there is no ID attribute.  Each
+   attribute/value pair counts as 2; thus this correspondds to an index
+   into the atts array passed to the XML_StartElementHandler.
+*/
+int XMLPARSEAPI
+xmlrpc_XML_GetIdAttributeIndex(XML_Parser parser);
+
+/* Parses some input. Returns 0 if a fatal error is detected.
+   The last call to XML_Parse must have isFinal true;
+   len may be zero for this call (or any other).
+*/
+int XMLPARSEAPI
+xmlrpc_XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+void XMLPARSEAPI *
+xmlrpc_XML_GetBuffer(XML_Parser parser, int len);
+
+int XMLPARSEAPI
+xmlrpc_XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Creates an XML_Parser object that can parse an external general
+   entity; context is a '\0'-terminated string specifying the parse
+   context; encoding is a '\0'-terminated string giving the name of the
+   externally specified encoding, or null if there is no externally
+   specified encoding.  The context string consists of a sequence of
+   tokens separated by formfeeds (\f); a token consisting of a name
+   specifies that the general entity of the name is open; a token of the
+   form prefix=uri specifies the namespace for a particular prefix; a
+   token of the form =uri specifies the default namespace.  This can be
+   called at any point after the first call to an
+   ExternalEntityRefHandler so longer as the parser has not yet been
+   freed.  The new parser is completely independent and may safely be
+   used in a separate thread.  The handlers and userData are initialized
+   from the parser argument.  Returns 0 if out of memory.  Otherwise
+   returns a new XML_Parser object.
+*/
+XML_Parser XMLPARSEAPI
+xmlrpc_XML_ExternalEntityParserCreate(XML_Parser parser,
+                                      const XML_Char *context,
+                                      const XML_Char *encoding);
+
+enum XML_ParamEntityParsing {
+  XML_PARAM_ENTITY_PARSING_NEVER,
+  XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
+  XML_PARAM_ENTITY_PARSING_ALWAYS
+};
+
+/* Controls parsing of parameter entities (including the external DTD
+   subset). If parsing of parameter entities is enabled, then references
+   to external parameter entities (including the external DTD subset)
+   will be passed to the handler set with
+   XML_SetExternalEntityRefHandler.  The context passed will be 0.
+   Unlike external general entities, external parameter entities can only
+   be parsed synchronously.  If the external parameter entity is to be
+   parsed, it must be parsed during the call to the external entity ref
+   handler: the complete sequence of XML_ExternalEntityParserCreate,
+   XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during
+   this call.  After XML_ExternalEntityParserCreate has been called to
+   create the parser for the external parameter entity (context must be 0
+   for this call), it is illegal to make any calls on the old parser
+   until XML_ParserFree has been called on the newly created parser.  If
+   the library has been compiled without support for parameter entity
+   parsing (ie without XML_DTD being defined), then
+   XML_SetParamEntityParsing will return 0 if parsing of parameter
+   entities is requested; otherwise it will return non-zero.
+*/
+int XMLPARSEAPI
+xmlrpc_XML_SetParamEntityParsing(XML_Parser parser,
+                                 enum XML_ParamEntityParsing parsing);
+
+enum XML_Error {
+  XML_ERROR_NONE,
+  XML_ERROR_NO_MEMORY,
+  XML_ERROR_SYNTAX,
+  XML_ERROR_NO_ELEMENTS,
+  XML_ERROR_INVALID_TOKEN,
+  XML_ERROR_UNCLOSED_TOKEN,
+  XML_ERROR_PARTIAL_CHAR,
+  XML_ERROR_TAG_MISMATCH,
+  XML_ERROR_DUPLICATE_ATTRIBUTE,
+  XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+  XML_ERROR_PARAM_ENTITY_REF,
+  XML_ERROR_UNDEFINED_ENTITY,
+  XML_ERROR_RECURSIVE_ENTITY_REF,
+  XML_ERROR_ASYNC_ENTITY,
+  XML_ERROR_BAD_CHAR_REF,
+  XML_ERROR_BINARY_ENTITY_REF,
+  XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+  XML_ERROR_MISPLACED_XML_PI,
+  XML_ERROR_UNKNOWN_ENCODING,
+  XML_ERROR_INCORRECT_ENCODING,
+  XML_ERROR_UNCLOSED_CDATA_SECTION,
+  XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+  XML_ERROR_NOT_STANDALONE
+};
+
+/* If xmlrpc_XML_Parse or xmlrpc_XML_ParseBuffer have returned 0, then
+   xmlrpc_XML_GetErrorCode returns information about the error.
+*/
+
+enum XML_Error XMLPARSEAPI
+xmlrpc_XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse location.
+   They may be called when XML_Parse or XML_ParseBuffer return 0;
+   in this case the location is the location of the character at which
+   the error was detected.
+   They may also be called from any other callback called to report
+   some parse event; in this the location is the location of the first
+   of the sequence of characters that generated the event.
+*/
+
+int XMLPARSEAPI
+xmlrpc_XML_GetCurrentLineNumber(XML_Parser parser);
+int XMLPARSEAPI
+xmlrpc_XML_GetCurrentColumnNumber(XML_Parser parser);
+long XMLPARSEAPI
+xmlrpc_XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+Returns 0 if the event is in an internal entity. */
+
+int XMLPARSEAPI
+xmlrpc_XML_GetCurrentByteCount(XML_Parser parser);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
+
+/* Frees memory used by the parser. */
+void XMLPARSEAPI
+xmlrpc_XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+const XML_LChar XMLPARSEAPI *
+xmlrpc_XML_ErrorString(int code);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/expat/xmltok/.cvsignore b/lib/expat/xmltok/.cvsignore
new file mode 100644 (file)
index 0000000..38cd01c
--- /dev/null
@@ -0,0 +1 @@
+nametab.h
diff --git a/lib/expat/xmltok/Makefile b/lib/expat/xmltok/Makefile
new file mode 100644 (file)
index 0000000..2af8543
--- /dev/null
@@ -0,0 +1,66 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../../..
+endif
+
+include $(SRCDIR)/Makefile.config
+
+# I can't figure out what XML_BYTE_ORDER is, but it doesn't look like the
+# code has ever defined it.  That means it's treated like 0 in #if.  Since
+# we started using the Gcc -Wundef option, that generates a warning, so
+# se set it explicitly to 0 here.
+
+CFLAGS = $(CFLAGS_COMMON) -DXML_BYTE_ORDER=0 $(CFLAGS_PERSONAL) $(CADD)
+
+LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR) $(LADD)
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/lib/util/include
+
+default: all
+
+include $(SRCDIR)/Makefile.common
+
+.PHONY: all
+all: libxmlrpc_xmltok.la
+
+.PHONY: clean
+clean: clean-common
+       rm -f nametab.h
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: tags
+tags: TAGS
+
+.PHONY: distdir
+distdir:
+
+.PHONY: install
+install: install-common
+
+.PHONY: dep
+dep: dep-common
+
+LTLIBRARIES_TO_INSTALL = libxmlrpc_xmltok.la
+
+LIBXMLRPC_XMLTOK_OBJS = xmltok.lo xmlrole.lo
+
+libxmlrpc_xmltok.la: $(LIBXMLRPC_XMLTOK_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+
+$(LIBXMLRPC_XMLTOK_OBJS):%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(LIBXML_INCLUDES) \
+         $(CFLAGS) $<
+
+GENNMTAB = ../gennmtab/gennmtab
+
+nametab.h: $(GENNMTAB)
+       rm -f $@
+       $(GENNMTAB) >$@ || (rm -f $@ || false)
+
+$(GENNMTAB):
+       $(MAKE) -C $(dir $@) $(notdir $@)
+
+xmltok.lo: nametab.h
+
+include Makefile.depend
diff --git a/lib/expat/xmltok/Makefile.depend b/lib/expat/xmltok/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/expat/xmltok/ascii.h b/lib/expat/xmltok/ascii.h
new file mode 100644 (file)
index 0000000..a8a621c
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#define ASCII_A 0x41
+#define ASCII_B 0x42
+#define ASCII_C 0x43
+#define ASCII_D 0x44
+#define ASCII_E 0x45
+#define ASCII_F 0x46
+#define ASCII_G 0x47
+#define ASCII_H 0x48
+#define ASCII_I 0x49
+#define ASCII_J 0x4A
+#define ASCII_K 0x4B
+#define ASCII_L 0x4C
+#define ASCII_M 0x4D
+#define ASCII_N 0x4E
+#define ASCII_O 0x4F
+#define ASCII_P 0x50
+#define ASCII_Q 0x51
+#define ASCII_R 0x52
+#define ASCII_S 0x53
+#define ASCII_T 0x54
+#define ASCII_U 0x55
+#define ASCII_V 0x56
+#define ASCII_W 0x57
+#define ASCII_X 0x58
+#define ASCII_Y 0x59
+#define ASCII_Z 0x5A
+
+#define ASCII_a 0x61
+#define ASCII_b 0x62
+#define ASCII_c 0x63
+#define ASCII_d 0x64
+#define ASCII_e 0x65
+#define ASCII_f 0x66
+#define ASCII_g 0x67
+#define ASCII_h 0x68
+#define ASCII_i 0x69
+#define ASCII_j 0x6A
+#define ASCII_k 0x6B
+#define ASCII_l 0x6C
+#define ASCII_m 0x6D
+#define ASCII_n 0x6E
+#define ASCII_o 0x6F
+#define ASCII_p 0x70
+#define ASCII_q 0x71
+#define ASCII_r 0x72
+#define ASCII_s 0x73
+#define ASCII_t 0x74
+#define ASCII_u 0x75
+#define ASCII_v 0x76
+#define ASCII_w 0x77
+#define ASCII_x 0x78
+#define ASCII_y 0x79
+#define ASCII_z 0x7A
+
+#define ASCII_0 0x30
+#define ASCII_1 0x31
+#define ASCII_2 0x32
+#define ASCII_3 0x33
+#define ASCII_4 0x34
+#define ASCII_5 0x35
+#define ASCII_6 0x36
+#define ASCII_7 0x37
+#define ASCII_8 0x38
+#define ASCII_9 0x39
+
+#define ASCII_TAB 0x09
+#define ASCII_SPACE 0x20 
+#define ASCII_EXCL 0x21
+#define ASCII_QUOT 0x22
+#define ASCII_AMP 0x26
+#define ASCII_APOS 0x27
+#define ASCII_MINUS 0x2D
+#define ASCII_PERIOD 0x2E
+#define ASCII_COLON 0x3A
+#define ASCII_SEMI 0x3B
+#define ASCII_LT 0x3C
+#define ASCII_EQUALS 0x3D
+#define ASCII_GT 0x3E
+#define ASCII_LSQB 0x5B
+#define ASCII_RSQB 0x5D
+#define ASCII_UNDERSCORE 0x5F
diff --git a/lib/expat/xmltok/asciitab.h b/lib/expat/xmltok/asciitab.h
new file mode 100644 (file)
index 0000000..e994576
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/lib/expat/xmltok/dllmain.c b/lib/expat/xmltok/dllmain.c
new file mode 100644 (file)
index 0000000..d5aa4a3
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#define STRICT 1
+#define WIN32_LEAN_AND_MEAN 1
+
+#include <windows.h>
+
+BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
+{
+  return TRUE;
+}
+
diff --git a/lib/expat/xmltok/iasciitab.h b/lib/expat/xmltok/iasciitab.h
new file mode 100644 (file)
index 0000000..2694d9d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/lib/expat/xmltok/latin1tab.h b/lib/expat/xmltok/latin1tab.h
new file mode 100644 (file)
index 0000000..6e01d50
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
+/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
diff --git a/lib/expat/xmltok/utf8tab.h b/lib/expat/xmltok/utf8tab.h
new file mode 100644 (file)
index 0000000..28d9b59
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+
+/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
+/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
diff --git a/lib/expat/xmltok/xmldef.h b/lib/expat/xmltok/xmldef.h
new file mode 100644 (file)
index 0000000..57b8333
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#include <string.h>
+
+#ifdef XML_WINLIB
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+
+#define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x))
+#define calloc(x, y) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)*(y))
+#define free(x) HeapFree(GetProcessHeap(), 0, (x))
+#define realloc(x, y) HeapReAlloc(GetProcessHeap(), 0, x, y)
+#define abort() /* as nothing */
+
+#else /* not XML_WINLIB */
+
+#include <stdlib.h>
+
+#endif /* not XML_WINLIB */
+
+/* This file can be used for any definitions needed in
+particular environments. */
+
+/* Mozilla specific defines */
+
+#ifdef MOZILLA_CLIENT
+
+#include "nspr.h"
+#define malloc(x) PR_Malloc((size_t)(x))
+#define realloc(x, y) PR_Realloc((x), (size_t)(y))
+#define calloc(x, y) PR_Calloc((x),(y))
+#define free(x) PR_Free(x)
+#if PR_BYTES_PER_INT != 4
+#define int int32
+#endif
+
+/* Enable Unicode string processing in expat. */
+#ifndef XML_UNICODE
+#define XML_UNICODE
+#endif
+
+/* Enable external parameter entity parsing in expat */
+#ifndef XML_DTD
+#define XML_DTD 1
+#endif
+
+#endif /* MOZILLA_CLIENT */
diff --git a/lib/expat/xmltok/xmlrole.c b/lib/expat/xmltok/xmlrole.c
new file mode 100644 (file)
index 0000000..04144d7
--- /dev/null
@@ -0,0 +1,1266 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+#include "xmlrpc_config.h"
+
+#include "xmldef.h"
+#include "xmlrole.h"
+#include "ascii.h"
+
+/* Doesn't check:
+
+ that ,| are not mixed in a model group
+ content of literals
+
+*/
+
+static const char KW_ANY[] = { ASCII_A, ASCII_N, ASCII_Y, '\0' };
+static const char KW_ATTLIST[] = { ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' };
+static const char KW_CDATA[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_DOCTYPE[] = { ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' };
+static const char KW_ELEMENT[] = { ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' };
+static const char KW_EMPTY[] = { ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' };
+static const char KW_ENTITIES[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
+static const char KW_ENTITY[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
+static const char KW_FIXED[] = { ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' };
+static const char KW_ID[] = { ASCII_I, ASCII_D, '\0' };
+static const char KW_IDREF[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
+static const char KW_IDREFS[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
+static const char KW_IGNORE[] = { ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' };
+static const char KW_IMPLIED[] = { ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' };
+static const char KW_INCLUDE[] = { ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' };
+static const char KW_NDATA[] = { ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_NMTOKEN[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
+static const char KW_NMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
+static const char KW_NOTATION[] = { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, '\0' };
+static const char KW_PCDATA[] = { ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_PUBLIC[] = { ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' };
+static const char KW_REQUIRED[] = { ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, '\0' };
+static const char KW_SYSTEM[] = { ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' };
+
+#ifndef MIN_BYTES_PER_CHAR
+#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
+#endif
+
+#ifdef XML_DTD
+#define setTopLevel(state) \
+  ((state)->handler = ((state)->documentEntity \
+                       ? internalSubset \
+                       : externalSubset1))
+#else /* not XML_DTD */
+#define setTopLevel(state) ((state)->handler = internalSubset)
+#endif /* not XML_DTD */
+
+typedef int PROLOG_HANDLER(PROLOG_STATE *state,
+                          int tok,
+                          const char *ptr,
+                          const char *end,
+                          const ENCODING *enc);
+
+static PROLOG_HANDLER
+  prolog0, prolog1, prolog2,
+  doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
+  internalSubset,
+  entity0, entity1, entity2, entity3, entity4, entity5, entity6,
+  entity7, entity8, entity9,
+  notation0, notation1, notation2, notation3, notation4,
+  attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
+  attlist7, attlist8, attlist9,
+  element0, element1, element2, element3, element4, element5, element6,
+  element7,
+#ifdef XML_DTD
+  externalSubset0, externalSubset1,
+  condSect0, condSect1, condSect2,
+#endif /* XML_DTD */
+  declClose,
+  error;
+
+static
+int common(PROLOG_STATE *state, int tok);
+
+static
+int prolog0(PROLOG_STATE *state,
+           int tok,
+           const char *ptr,
+           const char *end,
+           const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    state->handler = prolog1;
+    return XML_ROLE_NONE;
+  case XML_TOK_XML_DECL:
+    state->handler = prolog1;
+    return XML_ROLE_XML_DECL;
+  case XML_TOK_PI:
+    state->handler = prolog1;
+    return XML_ROLE_NONE;
+  case XML_TOK_COMMENT:
+    state->handler = prolog1;
+  case XML_TOK_BOM:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_OPEN:
+    if (!XmlNameMatchesAscii(enc,
+                            ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_DOCTYPE))
+      break;
+    state->handler = doctype0;
+    return XML_ROLE_NONE;
+  case XML_TOK_INSTANCE_START:
+    state->handler = error;
+    return XML_ROLE_INSTANCE_START;
+  }
+  return common(state, tok);
+}
+
+static
+int prolog1(PROLOG_STATE *state,
+           int tok,
+           const char *ptr,
+           const char *end,
+           const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_PI:
+  case XML_TOK_COMMENT:
+  case XML_TOK_BOM:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_OPEN:
+    if (!XmlNameMatchesAscii(enc,
+                            ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_DOCTYPE))
+      break;
+    state->handler = doctype0;
+    return XML_ROLE_NONE;
+  case XML_TOK_INSTANCE_START:
+    state->handler = error;
+    return XML_ROLE_INSTANCE_START;
+  }
+  return common(state, tok);
+}
+
+static
+int prolog2(PROLOG_STATE *state,
+           int tok,
+           const char *ptr ATTR_UNUSED,
+           const char *end ATTR_UNUSED,
+           const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_PI:
+  case XML_TOK_COMMENT:
+    return XML_ROLE_NONE;
+  case XML_TOK_INSTANCE_START:
+    state->handler = error;
+    return XML_ROLE_INSTANCE_START;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype0(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = doctype1;
+    return XML_ROLE_DOCTYPE_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype1(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_BRACKET:
+    state->handler = internalSubset;
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    state->handler = prolog2;
+    return XML_ROLE_DOCTYPE_CLOSE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+      state->handler = doctype3;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+      state->handler = doctype2;
+      return XML_ROLE_NONE;
+    }
+    break;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype2(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = doctype3;
+    return XML_ROLE_DOCTYPE_PUBLIC_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype3(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = doctype4;
+    return XML_ROLE_DOCTYPE_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype4(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_BRACKET:
+    state->handler = internalSubset;
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    state->handler = prolog2;
+    return XML_ROLE_DOCTYPE_CLOSE;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype5(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    state->handler = prolog2;
+    return XML_ROLE_DOCTYPE_CLOSE;
+  }
+  return common(state, tok);
+}
+
+static
+int internalSubset(PROLOG_STATE *state,
+                  int tok,
+                  const char *ptr,
+                  const char *end,
+                  const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_OPEN:
+    if (XmlNameMatchesAscii(enc,
+                           ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                           end,
+                           KW_ENTITY)) {
+      state->handler = entity0;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                           ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                           end,
+                           KW_ATTLIST)) {
+      state->handler = attlist0;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                           ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                           end,
+                           KW_ELEMENT)) {
+      state->handler = element0;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                           ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                           end,
+                           KW_NOTATION)) {
+      state->handler = notation0;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_PI:
+  case XML_TOK_COMMENT:
+    return XML_ROLE_NONE;
+  case XML_TOK_PARAM_ENTITY_REF:
+    return XML_ROLE_PARAM_ENTITY_REF;
+  case XML_TOK_CLOSE_BRACKET:
+    state->handler = doctype5;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static
+int externalSubset0(PROLOG_STATE *state,
+                   int tok,
+                   const char *ptr,
+                   const char *end,
+                   const ENCODING *enc)
+{
+  state->handler = externalSubset1;
+  if (tok == XML_TOK_XML_DECL)
+    return XML_ROLE_TEXT_DECL;
+  return externalSubset1(state, tok, ptr, end, enc);
+}
+
+static
+int externalSubset1(PROLOG_STATE *state,
+                   int tok,
+                   const char *ptr,
+                   const char *end,
+                   const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_COND_SECT_OPEN:
+    state->handler = condSect0;
+    return XML_ROLE_NONE;
+  case XML_TOK_COND_SECT_CLOSE:
+    if (state->includeLevel == 0)
+      break;
+    state->includeLevel -= 1;
+    return XML_ROLE_NONE;
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_BRACKET:
+    break;
+  case XML_TOK_NONE:
+    if (state->includeLevel)
+      break;
+    return XML_ROLE_NONE;
+  default:
+    return internalSubset(state, tok, ptr, end, enc);
+  }
+  return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static
+int entity0(PROLOG_STATE *state,
+           int tok,
+           const char *ptr ATTR_UNUSED,
+           const char *end ATTR_UNUSED,
+           const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_PERCENT:
+    state->handler = entity1;
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = entity2;
+    return XML_ROLE_GENERAL_ENTITY_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int entity1(PROLOG_STATE *state,
+           int tok,
+           const char *ptr ATTR_UNUSED,
+           const char *end ATTR_UNUSED,
+           const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = entity7;
+    return XML_ROLE_PARAM_ENTITY_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int entity2(PROLOG_STATE *state,
+           int tok,
+           const char *ptr,
+           const char *end,
+           const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+      state->handler = entity4;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+      state->handler = entity3;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_ENTITY_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int entity3(PROLOG_STATE *state,
+           int tok,
+           const char *ptr ATTR_UNUSED,
+           const char *end ATTR_UNUSED,
+           const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = entity4;
+    return XML_ROLE_ENTITY_PUBLIC_ID;
+  }
+  return common(state, tok);
+}
+
+
+static
+int entity4(PROLOG_STATE *state,
+           int tok,
+           const char *ptr ATTR_UNUSED,
+           const char *end ATTR_UNUSED,
+           const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = entity5;
+    return XML_ROLE_ENTITY_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int entity5(PROLOG_STATE *state,
+           int tok,
+           const char *ptr,
+           const char *end,
+           const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    setTopLevel(state);
+    return XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) {
+      state->handler = entity6;
+      return XML_ROLE_NONE;
+    }
+    break;
+  }
+  return common(state, tok);
+}
+
+static
+int entity6(PROLOG_STATE *state,
+           int tok,
+           const char *ptr ATTR_UNUSED,
+           const char *end ATTR_UNUSED,
+           const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = declClose;
+    return XML_ROLE_ENTITY_NOTATION_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int entity7(PROLOG_STATE *state,
+           int tok,
+           const char *ptr,
+           const char *end,
+           const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+      state->handler = entity9;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+      state->handler = entity8;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_ENTITY_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int entity8(PROLOG_STATE *state,
+           int tok,
+           const char *ptr ATTR_UNUSED,
+           const char *end ATTR_UNUSED,
+           const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = entity9;
+    return XML_ROLE_ENTITY_PUBLIC_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int entity9(PROLOG_STATE *state,
+           int tok,
+           const char *ptr ATTR_UNUSED,
+           const char *end ATTR_UNUSED,
+           const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_ENTITY_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int notation0(PROLOG_STATE *state,
+             int tok,
+             const char *ptr ATTR_UNUSED,
+             const char *end ATTR_UNUSED,
+             const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = notation1;
+    return XML_ROLE_NOTATION_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int notation1(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+      state->handler = notation3;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+      state->handler = notation2;
+      return XML_ROLE_NONE;
+    }
+    break;
+  }
+  return common(state, tok);
+}
+
+static
+int notation2(PROLOG_STATE *state,
+             int tok,
+             const char *ptr ATTR_UNUSED,
+             const char *end ATTR_UNUSED,
+             const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = notation4;
+    return XML_ROLE_NOTATION_PUBLIC_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int notation3(PROLOG_STATE *state,
+             int tok,
+             const char *ptr ATTR_UNUSED,
+             const char *end ATTR_UNUSED,
+             const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_NOTATION_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int notation4(PROLOG_STATE *state,
+             int tok,
+             const char *ptr ATTR_UNUSED,
+             const char *end ATTR_UNUSED,
+             const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_NOTATION_SYSTEM_ID;
+  case XML_TOK_DECL_CLOSE:
+    setTopLevel(state);
+    return XML_ROLE_NOTATION_NO_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist0(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = attlist1;
+    return XML_ROLE_ATTLIST_ELEMENT_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist1(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    setTopLevel(state);
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = attlist2;
+    return XML_ROLE_ATTRIBUTE_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist2(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    {
+      static const char *types[] = {
+       KW_CDATA,
+        KW_ID,
+        KW_IDREF,
+        KW_IDREFS,
+        KW_ENTITY,
+        KW_ENTITIES,
+        KW_NMTOKEN,
+        KW_NMTOKENS,
+      };
+      int i;
+      for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
+       if (XmlNameMatchesAscii(enc, ptr, end, types[i])) {
+         state->handler = attlist8;
+         return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
+       }
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) {
+      state->handler = attlist5;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_OPEN_PAREN:
+    state->handler = attlist3;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist3(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NMTOKEN:
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = attlist4;
+    return XML_ROLE_ATTRIBUTE_ENUM_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist4(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN:
+    state->handler = attlist8;
+    return XML_ROLE_NONE;
+  case XML_TOK_OR:
+    state->handler = attlist3;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist5(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_PAREN:
+    state->handler = attlist6;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+
+static
+int attlist6(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = attlist7;
+    return XML_ROLE_ATTRIBUTE_NOTATION_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist7(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN:
+    state->handler = attlist8;
+    return XML_ROLE_NONE;
+  case XML_TOK_OR:
+    state->handler = attlist6;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+/* default value */
+static
+int attlist8(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_POUND_NAME:
+    if (XmlNameMatchesAscii(enc,
+                           ptr + MIN_BYTES_PER_CHAR(enc),
+                           end,
+                           KW_IMPLIED)) {
+      state->handler = attlist1;
+      return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                           ptr + MIN_BYTES_PER_CHAR(enc),
+                           end,
+                           KW_REQUIRED)) {
+      state->handler = attlist1;
+      return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                           ptr + MIN_BYTES_PER_CHAR(enc),
+                           end,
+                           KW_FIXED)) {
+      state->handler = attlist9;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_LITERAL:
+    state->handler = attlist1;
+    return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist9(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = attlist1;
+    return XML_ROLE_FIXED_ATTRIBUTE_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int element0(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = element1;
+    return XML_ROLE_ELEMENT_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int element1(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) {
+      state->handler = declClose;
+      return XML_ROLE_CONTENT_EMPTY;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) {
+      state->handler = declClose;
+      return XML_ROLE_CONTENT_ANY;
+    }
+    break;
+  case XML_TOK_OPEN_PAREN:
+    state->handler = element2;
+    state->level = 1;
+    return XML_ROLE_GROUP_OPEN;
+  }
+  return common(state, tok);
+}
+
+static
+int element2(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_POUND_NAME:
+    if (XmlNameMatchesAscii(enc,
+                           ptr + MIN_BYTES_PER_CHAR(enc),
+                           end,
+                           KW_PCDATA)) {
+      state->handler = element3;
+      return XML_ROLE_CONTENT_PCDATA;
+    }
+    break;
+  case XML_TOK_OPEN_PAREN:
+    state->level = 2;
+    state->handler = element6;
+    return XML_ROLE_GROUP_OPEN;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT;
+  case XML_TOK_NAME_QUESTION:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_OPT;
+  case XML_TOK_NAME_ASTERISK:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_REP;
+  case XML_TOK_NAME_PLUS:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_PLUS;
+  }
+  return common(state, tok);
+}
+
+static
+int element3(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN:
+  case XML_TOK_CLOSE_PAREN_ASTERISK:
+    state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_REP;
+  case XML_TOK_OR:
+    state->handler = element4;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int element4(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = element5;
+    return XML_ROLE_CONTENT_ELEMENT;
+  }
+  return common(state, tok);
+}
+
+static
+int element5(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN_ASTERISK:
+    state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_REP;
+  case XML_TOK_OR:
+    state->handler = element4;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int element6(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_PAREN:
+    state->level += 1;
+    return XML_ROLE_GROUP_OPEN;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT;
+  case XML_TOK_NAME_QUESTION:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_OPT;
+  case XML_TOK_NAME_ASTERISK:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_REP;
+  case XML_TOK_NAME_PLUS:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_PLUS;
+  }
+  return common(state, tok);
+}
+
+static
+int element7(PROLOG_STATE *state,
+            int tok,
+            const char *ptr ATTR_UNUSED,
+            const char *end ATTR_UNUSED,
+            const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN:
+    state->level -= 1;
+    if (state->level == 0)
+      state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE;
+  case XML_TOK_CLOSE_PAREN_ASTERISK:
+    state->level -= 1;
+    if (state->level == 0)
+      state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_REP;
+  case XML_TOK_CLOSE_PAREN_QUESTION:
+    state->level -= 1;
+    if (state->level == 0)
+      state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_OPT;
+  case XML_TOK_CLOSE_PAREN_PLUS:
+    state->level -= 1;
+    if (state->level == 0)
+      state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_PLUS;
+  case XML_TOK_COMMA:
+    state->handler = element6;
+    return XML_ROLE_GROUP_SEQUENCE;
+  case XML_TOK_OR:
+    state->handler = element6;
+    return XML_ROLE_GROUP_CHOICE;
+  }
+  return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static
+int condSect0(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) {
+      state->handler = condSect1;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) {
+      state->handler = condSect2;
+      return XML_ROLE_NONE;
+    }
+    break;
+  }
+  return common(state, tok);
+}
+
+static
+int condSect1(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_BRACKET:
+    state->handler = externalSubset1;
+    state->includeLevel += 1;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int condSect2(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_BRACKET:
+    state->handler = externalSubset1;
+    return XML_ROLE_IGNORE_SECT;
+  }
+  return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static
+int declClose(PROLOG_STATE *state,
+             int tok,
+             const char *ptr ATTR_UNUSED,
+             const char *end ATTR_UNUSED,
+             const ENCODING *enc ATTR_UNUSED)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    setTopLevel(state);
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+#if 0
+
+static
+int ignore(PROLOG_STATE *state,
+          int tok,
+          const char *ptr,
+          const char *end,
+          const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_DECL_CLOSE:
+    state->handler = internalSubset;
+    return 0;
+  default:
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+#endif
+
+static
+int error(PROLOG_STATE *state ATTR_UNUSED,
+         int tok ATTR_UNUSED,
+         const char *ptr ATTR_UNUSED,
+         const char *end ATTR_UNUSED,
+         const ENCODING *enc ATTR_UNUSED)
+{
+  return XML_ROLE_NONE;
+}
+
+static
+int common(PROLOG_STATE *state, int tok ATTR_UNUSED)
+{
+#ifdef XML_DTD
+  if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
+    return XML_ROLE_INNER_PARAM_ENTITY_REF;
+#endif
+  state->handler = error;
+  return XML_ROLE_ERROR;
+}
+
+void xmlrpc_XmlPrologStateInit(PROLOG_STATE *state)
+{
+  state->handler = prolog0;
+#ifdef XML_DTD
+  state->documentEntity = 1;
+  state->includeLevel = 0;
+#endif /* XML_DTD */
+}
+
+#ifdef XML_DTD
+
+void XmlPrologStateInitExternalEntity(PROLOG_STATE *state)
+{
+  state->handler = externalSubset0;
+  state->documentEntity = 0;
+  state->includeLevel = 0;
+}
+
+#endif /* XML_DTD */
diff --git a/lib/expat/xmltok/xmlrole.h b/lib/expat/xmltok/xmlrole.h
new file mode 100644 (file)
index 0000000..d604c72
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#ifndef XmlRole_INCLUDED
+#define XmlRole_INCLUDED 1
+
+#include "xmltok.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  XML_ROLE_ERROR = -1,
+  XML_ROLE_NONE = 0,
+  XML_ROLE_XML_DECL,
+  XML_ROLE_INSTANCE_START,
+  XML_ROLE_DOCTYPE_NAME,
+  XML_ROLE_DOCTYPE_SYSTEM_ID,
+  XML_ROLE_DOCTYPE_PUBLIC_ID,
+  XML_ROLE_DOCTYPE_CLOSE,
+  XML_ROLE_GENERAL_ENTITY_NAME,
+  XML_ROLE_PARAM_ENTITY_NAME,
+  XML_ROLE_ENTITY_VALUE,
+  XML_ROLE_ENTITY_SYSTEM_ID,
+  XML_ROLE_ENTITY_PUBLIC_ID,
+  XML_ROLE_ENTITY_NOTATION_NAME,
+  XML_ROLE_NOTATION_NAME,
+  XML_ROLE_NOTATION_SYSTEM_ID,
+  XML_ROLE_NOTATION_NO_SYSTEM_ID,
+  XML_ROLE_NOTATION_PUBLIC_ID,
+  XML_ROLE_ATTRIBUTE_NAME,
+  XML_ROLE_ATTRIBUTE_TYPE_CDATA,
+  XML_ROLE_ATTRIBUTE_TYPE_ID,
+  XML_ROLE_ATTRIBUTE_TYPE_IDREF,
+  XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
+  XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
+  XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
+  XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
+  XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
+  XML_ROLE_ATTRIBUTE_ENUM_VALUE,
+  XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
+  XML_ROLE_ATTLIST_ELEMENT_NAME,
+  XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
+  XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
+  XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
+  XML_ROLE_FIXED_ATTRIBUTE_VALUE,
+  XML_ROLE_ELEMENT_NAME,
+  XML_ROLE_CONTENT_ANY,
+  XML_ROLE_CONTENT_EMPTY,
+  XML_ROLE_CONTENT_PCDATA,
+  XML_ROLE_GROUP_OPEN,
+  XML_ROLE_GROUP_CLOSE,
+  XML_ROLE_GROUP_CLOSE_REP,
+  XML_ROLE_GROUP_CLOSE_OPT,
+  XML_ROLE_GROUP_CLOSE_PLUS,
+  XML_ROLE_GROUP_CHOICE,
+  XML_ROLE_GROUP_SEQUENCE,
+  XML_ROLE_CONTENT_ELEMENT,
+  XML_ROLE_CONTENT_ELEMENT_REP,
+  XML_ROLE_CONTENT_ELEMENT_OPT,
+  XML_ROLE_CONTENT_ELEMENT_PLUS,
+#ifdef XML_DTD
+  XML_ROLE_TEXT_DECL,
+  XML_ROLE_IGNORE_SECT,
+  XML_ROLE_INNER_PARAM_ENTITY_REF,
+#endif /* XML_DTD */
+  XML_ROLE_PARAM_ENTITY_REF,
+  XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION
+};
+
+typedef struct prolog_state {
+  int (*handler)(struct prolog_state *state,
+                int tok,
+                const char *ptr,
+                const char *end,
+                const ENCODING *enc);
+  unsigned level;
+#ifdef XML_DTD
+  unsigned includeLevel;
+  int documentEntity;
+#endif /* XML_DTD */
+} PROLOG_STATE;
+
+void XMLTOKAPI xmlrpc_XmlPrologStateInit(PROLOG_STATE *);
+#ifdef XML_DTD
+void XMLTOKAPI xmlrpc_XmlPrologStateInitExternalEntity(PROLOG_STATE *);
+#endif /* XML_DTD */
+
+#define XmlTokenRole(state, tok, ptr, end, enc) \
+ (((state)->handler)(state, tok, ptr, end, enc))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlRole_INCLUDED */
diff --git a/lib/expat/xmltok/xmltok.c b/lib/expat/xmltok/xmltok.c
new file mode 100644 (file)
index 0000000..b96fdaa
--- /dev/null
@@ -0,0 +1,1561 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#include "xmlrpc_config.h"
+#include "xmldef.h"
+#include "xmltok.h"
+#include "nametab.h"
+
+#ifdef XML_DTD
+#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
+#else
+#define IGNORE_SECTION_TOK_VTABLE /* as nothing */
+#endif
+
+#define VTABLE1 \
+  { PREFIX(prologTok), PREFIX(contentTok), \
+    PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \
+  { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
+  PREFIX(sameName), \
+  PREFIX(nameMatchesAscii), \
+  PREFIX(nameLength), \
+  PREFIX(skipS), \
+  PREFIX(getAtts), \
+  PREFIX(charRefNumber), \
+  PREFIX(predefinedEntityName), \
+  PREFIX(updatePosition), \
+  PREFIX(isPublicId)
+
+#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
+
+#define UCS2_GET_NAMING(pages, hi, lo) \
+   (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
+
+/* A 2 byte UTF-8 representation splits the characters 11 bits
+between the bottom 5 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING2(pages, byte) \
+    (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
+                      + ((((byte)[0]) & 3) << 1) \
+                      + ((((byte)[1]) >> 5) & 1)] \
+         & (1 << (((byte)[1]) & 0x1F)))
+
+/* A 3 byte UTF-8 representation splits the characters 16 bits
+between the bottom 4, 6 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING3(pages, byte) \
+  (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
+                             + ((((byte)[1]) >> 2) & 0xF)] \
+                      << 3) \
+                      + ((((byte)[1]) & 3) << 1) \
+                      + ((((byte)[2]) >> 5) & 1)] \
+         & (1 << (((byte)[2]) & 0x1F)))
+
+#define UTF8_GET_NAMING(pages, p, n) \
+  ((n) == 2 \
+  ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
+  : ((n) == 3 \
+     ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
+     : 0))
+
+#define UTF8_INVALID3(p) \
+  ((*p) == 0xED \
+  ? (((p)[1] & 0x20) != 0) \
+  : ((*p) == 0xEF \
+     ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \
+     : 0))
+
+#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0)
+
+static
+int isNever(const ENCODING *enc ATTR_UNUSED, const char *p ATTR_UNUSED)
+{
+  return 0;
+}
+
+static
+int utf8_isName2(const ENCODING *enc ATTR_UNUSED, const char *p)
+{
+  return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
+}
+
+static
+int utf8_isName3(const ENCODING *enc ATTR_UNUSED, const char *p)
+{
+  return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
+}
+
+#define utf8_isName4 isNever
+
+static
+int utf8_isNmstrt2(const ENCODING *enc ATTR_UNUSED, const char *p)
+{
+  return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
+}
+
+static
+int utf8_isNmstrt3(const ENCODING *enc ATTR_UNUSED, const char *p)
+{
+  return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
+}
+
+#define utf8_isNmstrt4 isNever
+
+#define utf8_isInvalid2 isNever
+
+static
+int utf8_isInvalid3(const ENCODING *enc ATTR_UNUSED, const char *p)
+{
+  return UTF8_INVALID3((const unsigned char *)p);
+}
+
+static
+int utf8_isInvalid4(const ENCODING *enc ATTR_UNUSED, const char *p)
+{
+  return UTF8_INVALID4((const unsigned char *)p);
+}
+
+struct normal_encoding {
+  ENCODING enc;
+  unsigned char type[256];
+#ifdef XML_MIN_SIZE
+  int (*byteType)(const ENCODING *, const char *);
+  int (*isNameMin)(const ENCODING *, const char *);
+  int (*isNmstrtMin)(const ENCODING *, const char *);
+  int (*byteToAscii)(const ENCODING *, const char *);
+  int (*charMatches)(const ENCODING *, const char *, int);
+#endif /* XML_MIN_SIZE */
+  int (*isName2)(const ENCODING *, const char *);
+  int (*isName3)(const ENCODING *, const char *);
+  int (*isName4)(const ENCODING *, const char *);
+  int (*isNmstrt2)(const ENCODING *, const char *);
+  int (*isNmstrt3)(const ENCODING *, const char *);
+  int (*isNmstrt4)(const ENCODING *, const char *);
+  int (*isInvalid2)(const ENCODING *, const char *);
+  int (*isInvalid3)(const ENCODING *, const char *);
+  int (*isInvalid4)(const ENCODING *, const char *);
+};
+
+#ifdef XML_MIN_SIZE
+
+#define STANDARD_VTABLE(E) \
+ E ## byteType, \
+ E ## isNameMin, \
+ E ## isNmstrtMin, \
+ E ## byteToAscii, \
+ E ## charMatches,
+
+#else
+
+#define STANDARD_VTABLE(E) /* as nothing */
+
+#endif
+
+#define NORMAL_VTABLE(E) \
+ E ## isName2, \
+ E ## isName3, \
+ E ## isName4, \
+ E ## isNmstrt2, \
+ E ## isNmstrt3, \
+ E ## isNmstrt4, \
+ E ## isInvalid2, \
+ E ## isInvalid3, \
+ E ## isInvalid4
+
+#define NULL_NORMAL_VTABLE \
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+
+static int checkCharRefNumber(int);
+
+#include "xmltok_impl.h"
+#include "ascii.h"
+
+#ifdef XML_MIN_SIZE
+#define sb_isNameMin isNever
+#define sb_isNmstrtMin isNever
+#endif
+
+#ifdef XML_MIN_SIZE
+#define MINBPC(enc) ((enc)->minBytesPerChar)
+#else
+/* minimum bytes per character */
+#define MINBPC(enc) 1
+#endif
+
+#define SB_BYTE_TYPE(enc, p) \
+  (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
+
+#ifdef XML_MIN_SIZE
+static
+int sb_byteType(const ENCODING *enc, const char *p)
+{
+  return SB_BYTE_TYPE(enc, p);
+}
+#define BYTE_TYPE(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteType(enc, p))
+#else
+#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define BYTE_TO_ASCII(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteToAscii(enc, p))
+static
+int sb_byteToAscii(const ENCODING *enc, const char *p)
+{
+  return *p;
+}
+#else
+#define BYTE_TO_ASCII(enc, p) (*(p))
+#endif
+
+#define IS_NAME_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isName ## n(enc, p))
+#define IS_NMSTRT_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p))
+#define IS_INVALID_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p))
+
+#ifdef XML_MIN_SIZE
+#define IS_NAME_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNameMin(enc, p))
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p))
+#else
+#define IS_NAME_CHAR_MINBPC(enc, p) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define CHAR_MATCHES(enc, p, c) \
+ (((const struct normal_encoding *)(enc))->charMatches(enc, p, c))
+static
+int sb_charMatches(const ENCODING *enc, const char *p, int c)
+{
+  return *p == c;
+}
+#else
+/* c is an ASCII character */
+#define CHAR_MATCHES(enc, p, c) (*(p) == c)
+#endif
+
+#define PREFIX(ident) normal_ ## ident
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+enum {  /* UTF8_cvalN is value of masked first byte of N byte sequence */
+  UTF8_cval1 = 0x00,
+  UTF8_cval2 = 0xc0,
+  UTF8_cval3 = 0xe0,
+  UTF8_cval4 = 0xf0
+};
+
+static
+void utf8_toUtf8(const ENCODING * enc ATTR_UNUSED,
+                const char **fromP, const char *fromLim,
+                char **toP, const char *toLim)
+{
+  char *to;
+  const char *from;
+  if (fromLim - *fromP > toLim - *toP) {
+    /* Avoid copying partial characters. */
+    for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
+      if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
+       break;
+  }
+  for (to = *toP, from = *fromP; from != fromLim; from++, to++)
+    *to = *from;
+  *fromP = from;
+  *toP = to;
+}
+
+static
+void utf8_toUtf16(const ENCODING *enc,
+                 const char **fromP, const char *fromLim,
+                 unsigned short **toP, const unsigned short *toLim)
+{
+  unsigned short *to = *toP;
+  const char *from = *fromP;
+  while (from != fromLim && to != toLim) {
+    switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
+    case BT_LEAD2:
+      *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f);
+      from += 2;
+      break;
+    case BT_LEAD3:
+      *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f);
+      from += 3;
+      break;
+    case BT_LEAD4:
+      {
+       unsigned long n;
+       if (to + 1 == toLim)
+         break;
+       n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+       n -= 0x10000;
+       to[0] = (unsigned short)((n >> 10) | 0xD800);
+       to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
+       to += 2;
+       from += 4;
+      }
+      break;
+    default:
+      *to++ = *from++;
+      break;
+    }
+  }
+  *fromP = from;
+  *toP = to;
+}
+
+#ifdef XML_NS
+static const struct normal_encoding utf8_encoding_ns = {
+  { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+  {
+#include "asciitab.h"
+#include "utf8tab.h"
+  },
+  STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+#endif
+
+static const struct normal_encoding utf8_encoding = {
+  { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+  },
+  STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_utf8_encoding_ns = {
+  { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+  {
+#include "iasciitab.h"
+#include "utf8tab.h"
+  },
+  STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#endif
+
+static const struct normal_encoding internal_utf8_encoding = {
+  { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+  },
+  STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+static
+void latin1_toUtf8(const ENCODING *enc ATTR_UNUSED,
+                  const char **fromP, const char *fromLim,
+                  char **toP, const char *toLim)
+{
+  for (;;) {
+    unsigned char c;
+    if (*fromP == fromLim)
+      break;
+    c = (unsigned char)**fromP;
+    if (c & 0x80) {
+      if (toLim - *toP < 2)
+       break;
+      *(*toP)++ = ((c >> 6) | UTF8_cval2);
+      *(*toP)++ = ((c & 0x3f) | 0x80);
+      (*fromP)++;
+    }
+    else {
+      if (*toP == toLim)
+       break;
+      *(*toP)++ = *(*fromP)++;
+    }
+  }
+}
+
+static
+void latin1_toUtf16(const ENCODING *enc ATTR_UNUSED,
+                   const char **fromP, const char *fromLim,
+                   unsigned short **toP, const unsigned short *toLim)
+{
+  while (*fromP != fromLim && *toP != toLim)
+    *(*toP)++ = (unsigned char)*(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding latin1_encoding_ns = {
+  { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+  {
+#include "asciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding latin1_encoding = {
+  { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE
+};
+
+static
+void ascii_toUtf8(const ENCODING *enc ATTR_UNUSED,
+                 const char **fromP, const char *fromLim,
+                 char **toP, const char *toLim)
+{
+  while (*fromP != fromLim && *toP != toLim)
+    *(*toP)++ = *(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding ascii_encoding_ns = {
+  { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+  {
+#include "asciitab.h"
+/* BT_NONXML == 0 */
+  },
+  STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding ascii_encoding = {
+  { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+/* BT_NONXML == 0 */
+  },
+  STANDARD_VTABLE(sb_) NULL_NORMAL_VTABLE
+};
+
+static int unicode_byte_type(char hi, char lo)
+{
+  switch ((unsigned char)hi) {
+  case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+    return BT_LEAD4;
+  case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+    return BT_TRAIL;
+  case 0xFF:
+    switch ((unsigned char)lo) {
+    case 0xFF:
+    case 0xFE:
+      return BT_NONXML;
+    }
+    break;
+  }
+  return BT_NONASCII;
+}
+
+#define DEFINE_UTF16_TO_UTF8(E) \
+static \
+void E ## toUtf8(const ENCODING *enc ATTR_UNUSED, \
+                const char **fromP, const char *fromLim, \
+                char **toP, const char *toLim) \
+{ \
+  const char *from; \
+  for (from = *fromP; from != fromLim; from += 2) { \
+    int plane; \
+    unsigned char lo2; \
+    unsigned char lo = GET_LO(from); \
+    unsigned char hi = GET_HI(from); \
+    switch (hi) { \
+    case 0: \
+      if (lo < 0x80) { \
+        if (*toP == toLim) { \
+          *fromP = from; \
+         return; \
+        } \
+        *(*toP)++ = lo; \
+        break; \
+      } \
+      /* fall through */ \
+    case 0x1: case 0x2: case 0x3: \
+    case 0x4: case 0x5: case 0x6: case 0x7: \
+      if (toLim -  *toP < 2) { \
+        *fromP = from; \
+       return; \
+      } \
+      *(*toP)++ = ((lo >> 6) | (hi << 2) |  UTF8_cval2); \
+      *(*toP)++ = ((lo & 0x3f) | 0x80); \
+      break; \
+    default: \
+      if (toLim -  *toP < 3)  { \
+        *fromP = from; \
+       return; \
+      } \
+      /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+      *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+      *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
+      *(*toP)++ = ((lo & 0x3f) | 0x80); \
+      break; \
+    case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
+      if (toLim -  *toP < 4) { \
+       *fromP = from; \
+       return; \
+      } \
+      plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+      *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
+      *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
+      from += 2; \
+      lo2 = GET_LO(from); \
+      *(*toP)++ = (((lo & 0x3) << 4) \
+                  | ((GET_HI(from) & 0x3) << 2) \
+                  | (lo2 >> 6) \
+                  | 0x80); \
+      *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
+      break; \
+    } \
+  } \
+  *fromP = from; \
+}
+
+#define DEFINE_UTF16_TO_UTF16(E) \
+static \
+void E ## toUtf16(const ENCODING *enc ATTR_UNUSED, \
+                 const char **fromP, const char *fromLim, \
+                 unsigned short **toP, const unsigned short *toLim) \
+{ \
+  /* Avoid copying first half only of surrogate */ \
+  if (fromLim - *fromP > ((toLim - *toP) << 1) \
+      && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
+    fromLim -= 2; \
+  for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
+    *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
+}
+
+#define SET2(ptr, ch) \
+  (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[0])
+#define GET_HI(ptr) ((unsigned char)(ptr)[1])
+
+DEFINE_UTF16_TO_UTF8(little2_)
+DEFINE_UTF16_TO_UTF16(little2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define SET2(ptr, ch) \
+  (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[1])
+#define GET_HI(ptr) ((unsigned char)(ptr)[0])
+
+DEFINE_UTF16_TO_UTF8(big2_)
+DEFINE_UTF16_TO_UTF16(big2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define LITTLE2_BYTE_TYPE(enc, p) \
+ ((p)[1] == 0 \
+  ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
+  : unicode_byte_type((p)[1], (p)[0]))
+#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
+#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
+  UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
+#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+  UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+
+#ifdef XML_MIN_SIZE
+
+static
+int little2_byteType(const ENCODING *enc, const char *p)
+{
+  return LITTLE2_BYTE_TYPE(enc, p);
+}
+
+static
+int little2_byteToAscii(const ENCODING *enc, const char *p)
+{
+  return LITTLE2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int little2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+  return LITTLE2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int little2_isNameMin(const ENCODING *enc, const char *p)
+{
+  return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int little2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+  return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) little2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) 
+#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding little2_encoding_ns = { 
+  { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+    1
+#else
+    0
+#endif
+  },
+  {
+#include "asciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding little2_encoding = { 
+  { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+    1
+#else
+    0
+#endif
+  },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE
+};
+
+#if XML_BYTE_ORDER != 21
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_little2_encoding_ns = { 
+  { VTABLE, 2, 0, 1 },
+  {
+#include "iasciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding internal_little2_encoding = { 
+  { VTABLE, 2, 0, 1 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(little2_) NULL_NORMAL_VTABLE
+};
+
+#endif
+
+
+#define BIG2_BYTE_TYPE(enc, p) \
+ ((p)[0] == 0 \
+  ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
+  : unicode_byte_type((p)[0], (p)[1]))
+#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
+#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
+  UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
+#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+  UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+
+#ifdef XML_MIN_SIZE
+
+static
+int big2_byteType(const ENCODING *enc, const char *p)
+{
+  return BIG2_BYTE_TYPE(enc, p);
+}
+
+static
+int big2_byteToAscii(const ENCODING *enc, const char *p)
+{
+  return BIG2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int big2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+  return BIG2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int big2_isNameMin(const ENCODING *enc, const char *p)
+{
+  return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int big2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+  return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) big2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) 
+#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding big2_encoding_ns = {
+  { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+  1
+#else
+  0
+#endif
+  },
+  {
+#include "asciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding big2_encoding = {
+  { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+  1
+#else
+  0
+#endif
+  },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE
+};
+
+#if XML_BYTE_ORDER != 12
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_big2_encoding_ns = {
+  { VTABLE, 2, 0, 1 },
+  {
+#include "iasciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_big2_encoding = {
+  { VTABLE, 2, 0, 1 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(big2_) NULL_NORMAL_VTABLE
+};
+
+#endif
+
+#undef PREFIX
+
+static
+int streqci(const char *s1, const char *s2)
+{
+  for (;;) {
+    char c1 = *s1++;
+    char c2 = *s2++;
+    if (ASCII_a <= c1 && c1 <= ASCII_z)
+      c1 += ASCII_A - ASCII_a;
+    if (ASCII_a <= c2 && c2 <= ASCII_z)
+      c2 += ASCII_A - ASCII_a;
+    if (c1 != c2)
+      return 0;
+    if (!c1)
+      break;
+  }
+  return 1;
+}
+
+static
+void initUpdatePosition(const ENCODING *enc ATTR_UNUSED, const char *ptr,
+                       const char *end, POSITION *pos)
+{
+  normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
+}
+
+static
+int toAscii(const ENCODING *enc, const char *ptr, const char *end)
+{
+  char buf[1];
+  char *p = buf;
+  XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
+  if (p == buf)
+    return -1;
+  else
+    return buf[0];
+}
+
+static
+int isSpace(int c)
+{
+  switch (c) {
+  case 0x20:
+  case 0xD:
+  case 0xA:
+  case 0x9:    
+    return 1;
+  }
+  return 0;
+}
+
+/* Return 1 if there's just optional white space
+or there's an S followed by name=val. */
+static
+int parsePseudoAttribute(const ENCODING *enc,
+                        const char *ptr,
+                        const char *end,
+                        const char **namePtr,
+                        const char **nameEndPtr,
+                        const char **valPtr,
+                        const char **nextTokPtr)
+{
+  int c;
+  char open;
+  if (ptr == end) {
+    *namePtr = 0;
+    return 1;
+  }
+  if (!isSpace(toAscii(enc, ptr, end))) {
+    *nextTokPtr = ptr;
+    return 0;
+  }
+  do {
+    ptr += enc->minBytesPerChar;
+  } while (isSpace(toAscii(enc, ptr, end)));
+  if (ptr == end) {
+    *namePtr = 0;
+    return 1;
+  }
+  *namePtr = ptr;
+  for (;;) {
+    c = toAscii(enc, ptr, end);
+    if (c == -1) {
+      *nextTokPtr = ptr;
+      return 0;
+    }
+    if (c == ASCII_EQUALS) {
+      *nameEndPtr = ptr;
+      break;
+    }
+    if (isSpace(c)) {
+      *nameEndPtr = ptr;
+      do {
+       ptr += enc->minBytesPerChar;
+      } while (isSpace(c = toAscii(enc, ptr, end)));
+      if (c != ASCII_EQUALS) {
+       *nextTokPtr = ptr;
+       return 0;
+      }
+      break;
+    }
+    ptr += enc->minBytesPerChar;
+  }
+  if (ptr == *namePtr) {
+    *nextTokPtr = ptr;
+    return 0;
+  }
+  ptr += enc->minBytesPerChar;
+  c = toAscii(enc, ptr, end);
+  while (isSpace(c)) {
+    ptr += enc->minBytesPerChar;
+    c = toAscii(enc, ptr, end);
+  }
+  if (c != ASCII_QUOT && c != ASCII_APOS) {
+    *nextTokPtr = ptr;
+    return 0;
+  }
+  open = c;
+  ptr += enc->minBytesPerChar;
+  *valPtr = ptr;
+  for (;; ptr += enc->minBytesPerChar) {
+    c = toAscii(enc, ptr, end);
+    if (c == open)
+      break;
+    if (!(ASCII_a <= c && c <= ASCII_z)
+       && !(ASCII_A <= c && c <= ASCII_Z)
+       && !(ASCII_0 <= c && c <= ASCII_9)
+       && c != ASCII_PERIOD
+       && c != ASCII_MINUS
+       && c != ASCII_UNDERSCORE) {
+      *nextTokPtr = ptr;
+      return 0;
+    }
+  }
+  *nextTokPtr = ptr + enc->minBytesPerChar;
+  return 1;
+}
+
+static const char KW_version[] = {
+  ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'
+};
+
+static const char KW_encoding[] = {
+  ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0'
+};
+
+static const char KW_standalone[] = {
+  ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0'
+};
+
+static const char KW_yes[] = {
+  ASCII_y, ASCII_e, ASCII_s,  '\0'
+};
+
+static const char KW_no[] = {
+  ASCII_n, ASCII_o,  '\0'
+};
+
+static
+int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
+                                                    const char *,
+                                                    const char *),
+                  int isGeneralTextEntity,
+                  const ENCODING *enc,
+                  const char *ptr,
+                  const char *end,
+                  const char **badPtr,
+                  const char **versionPtr,
+                  const char **encodingName,
+                  const ENCODING **encoding,
+                  int *standalone)
+{
+  const char *val = 0;
+  const char *name = 0;
+  const char *nameEnd = 0;
+  ptr += 5 * enc->minBytesPerChar;
+  end -= 2 * enc->minBytesPerChar;
+  if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) || !name) {
+    *badPtr = ptr;
+    return 0;
+  }
+  if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
+    if (!isGeneralTextEntity) {
+      *badPtr = name;
+      return 0;
+    }
+  }
+  else {
+    if (versionPtr)
+      *versionPtr = val;
+    if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+      *badPtr = ptr;
+      return 0;
+    }
+    if (!name) {
+      if (isGeneralTextEntity) {
+       /* a TextDecl must have an EncodingDecl */
+       *badPtr = ptr;
+       return 0;
+      }
+      return 1;
+    }
+  }
+  if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
+    int c = toAscii(enc, val, end);
+    if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) {
+      *badPtr = val;
+      return 0;
+    }
+    if (encodingName)
+      *encodingName = val;
+    if (encoding)
+      *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
+    if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+      *badPtr = ptr;
+      return 0;
+    }
+    if (!name)
+      return 1;
+  }
+  if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) || isGeneralTextEntity) {
+    *badPtr = name;
+    return 0;
+  }
+  if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
+    if (standalone)
+      *standalone = 1;
+  }
+  else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
+    if (standalone)
+      *standalone = 0;
+  }
+  else {
+    *badPtr = val;
+    return 0;
+  }
+  while (isSpace(toAscii(enc, ptr, end)))
+    ptr += enc->minBytesPerChar;
+  if (ptr != end) {
+    *badPtr = ptr;
+    return 0;
+  }
+  return 1;
+}
+
+static
+int checkCharRefNumber(int result)
+{
+  switch (result >> 8) {
+  case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+  case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+    return -1;
+  case 0:
+    if (latin1_encoding.type[result] == BT_NONXML)
+      return -1;
+    break;
+  case 0xFF:
+    if (result == 0xFFFE || result == 0xFFFF)
+      return -1;
+    break;
+  }
+  return result;
+}
+
+int xmlrpc_XmlUtf8Encode(int c, char *buf)
+{
+  enum {
+    /* minN is minimum legal resulting value for N byte sequence */
+    min2 = 0x80,
+    min3 = 0x800,
+    min4 = 0x10000
+  };
+
+  if (c < 0)
+    return 0;
+  if (c < min2) {
+    buf[0] = (c | UTF8_cval1);
+    return 1;
+  }
+  if (c < min3) {
+    buf[0] = ((c >> 6) | UTF8_cval2);
+    buf[1] = ((c & 0x3f) | 0x80);
+    return 2;
+  }
+  if (c < min4) {
+    buf[0] = ((c >> 12) | UTF8_cval3);
+    buf[1] = (((c >> 6) & 0x3f) | 0x80);
+    buf[2] = ((c & 0x3f) | 0x80);
+    return 3;
+  }
+  if (c < 0x110000) {
+    buf[0] = ((c >> 18) | UTF8_cval4);
+    buf[1] = (((c >> 12) & 0x3f) | 0x80);
+    buf[2] = (((c >> 6) & 0x3f) | 0x80);
+    buf[3] = ((c & 0x3f) | 0x80);
+    return 4;
+  }
+  return 0;
+}
+
+int xmlrpc_XmlUtf16Encode(int charNum, unsigned short *buf)
+{
+  if (charNum < 0)
+    return 0;
+  if (charNum < 0x10000) {
+    buf[0] = charNum;
+    return 1;
+  }
+  if (charNum < 0x110000) {
+    charNum -= 0x10000;
+    buf[0] = (charNum >> 10) + 0xD800;
+    buf[1] = (charNum & 0x3FF) + 0xDC00;
+    return 2;
+  }
+  return 0;
+}
+
+struct unknown_encoding {
+  struct normal_encoding normal;
+  int (*convert)(void *userData, const char *p);
+  void *userData;
+  unsigned short utf16[256];
+  char utf8[256][4];
+};
+
+int xmlrpc_XmlSizeOfUnknownEncoding(void)
+{
+  return sizeof(struct unknown_encoding);
+}
+
+static
+int unknown_isName(const ENCODING *enc, const char *p)
+{
+  int c = ((const struct unknown_encoding *)enc)
+         ->convert(((const struct unknown_encoding *)enc)->userData, p);
+  if (c & ~0xFFFF)
+    return 0;
+  return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isNmstrt(const ENCODING *enc, const char *p)
+{
+  int c = ((const struct unknown_encoding *)enc)
+         ->convert(((const struct unknown_encoding *)enc)->userData, p);
+  if (c & ~0xFFFF)
+    return 0;
+  return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isInvalid(const ENCODING *enc, const char *p)
+{
+  int c = ((const struct unknown_encoding *)enc)
+          ->convert(((const struct unknown_encoding *)enc)->userData, p);
+  return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
+}
+
+static
+void unknown_toUtf8(const ENCODING *enc,
+                   const char **fromP, const char *fromLim,
+                   char **toP, const char *toLim)
+{
+  char buf[XML_UTF8_ENCODE_MAX];
+  for (;;) {
+    const char *utf8;
+    int n;
+    if (*fromP == fromLim)
+      break;
+    utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP];
+    n = *utf8++;
+    if (n == 0) {
+      int c = ((const struct unknown_encoding *)enc)
+             ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+      n = xmlrpc_XmlUtf8Encode(c, buf);
+      if (n > toLim - *toP)
+       break;
+      utf8 = buf;
+      *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+                - (BT_LEAD2 - 2);
+    }
+    else {
+      if (n > toLim - *toP)
+       break;
+      (*fromP)++;
+    }
+    do {
+      *(*toP)++ = *utf8++;
+    } while (--n != 0);
+  }
+}
+
+static
+void unknown_toUtf16(const ENCODING *enc,
+                    const char **fromP, const char *fromLim,
+                    unsigned short **toP, const unsigned short *toLim)
+{
+  while (*fromP != fromLim && *toP != toLim) {
+    unsigned short c
+      = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP];
+    if (c == 0) {
+      c = (unsigned short)((const struct unknown_encoding *)enc)
+          ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+      *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+                - (BT_LEAD2 - 2);
+    }
+    else
+      (*fromP)++;
+    *(*toP)++ = c;
+  }
+}
+
+ENCODING *
+xmlrpc_XmlInitUnknownEncoding(void *mem,
+                      int *table,
+                      int (*convert)(void *userData, const char *p),
+                      void *userData)
+{
+  int i;
+  struct unknown_encoding *e = mem;
+  for (i = 0; i < (int)sizeof(struct normal_encoding); i++)
+    ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+  for (i = 0; i < 128; i++)
+    if (latin1_encoding.type[i] != BT_OTHER
+        && latin1_encoding.type[i] != BT_NONXML
+       && table[i] != i)
+      return 0;
+  for (i = 0; i < 256; i++) {
+    int c = table[i];
+    if (c == -1) {
+      e->normal.type[i] = BT_MALFORM;
+      /* This shouldn't really get used. */
+      e->utf16[i] = 0xFFFF;
+      e->utf8[i][0] = 1;
+      e->utf8[i][1] = 0;
+    }
+    else if (c < 0) {
+      if (c < -4)
+       return 0;
+      e->normal.type[i] = BT_LEAD2 - (c + 2);
+      e->utf8[i][0] = 0;
+      e->utf16[i] = 0;
+    }
+    else if (c < 0x80) {
+      if (latin1_encoding.type[c] != BT_OTHER
+         && latin1_encoding.type[c] != BT_NONXML
+         && c != i)
+       return 0;
+      e->normal.type[i] = latin1_encoding.type[c];
+      e->utf8[i][0] = 1;
+      e->utf8[i][1] = (char)c;
+      e->utf16[i] = c == 0 ? 0xFFFF : c;
+    }
+    else if (checkCharRefNumber(c) < 0) {
+      e->normal.type[i] = BT_NONXML;
+      /* This shouldn't really get used. */
+      e->utf16[i] = 0xFFFF;
+      e->utf8[i][0] = 1;
+      e->utf8[i][1] = 0;
+    }
+    else {
+      if (c > 0xFFFF)
+       return 0;
+      if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
+       e->normal.type[i] = BT_NMSTRT;
+      else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
+       e->normal.type[i] = BT_NAME;
+      else
+       e->normal.type[i] = BT_OTHER;
+      e->utf8[i][0] = (char)xmlrpc_XmlUtf8Encode(c, e->utf8[i] + 1);
+      e->utf16[i] = c;
+    }
+  }
+  e->userData = userData;
+  e->convert = convert;
+  if (convert) {
+    e->normal.isName2 = unknown_isName;
+    e->normal.isName3 = unknown_isName;
+    e->normal.isName4 = unknown_isName;
+    e->normal.isNmstrt2 = unknown_isNmstrt;
+    e->normal.isNmstrt3 = unknown_isNmstrt;
+    e->normal.isNmstrt4 = unknown_isNmstrt;
+    e->normal.isInvalid2 = unknown_isInvalid;
+    e->normal.isInvalid3 = unknown_isInvalid;
+    e->normal.isInvalid4 = unknown_isInvalid;
+  }
+  e->normal.enc.utf8Convert = unknown_toUtf8;
+  e->normal.enc.utf16Convert = unknown_toUtf16;
+  return &(e->normal.enc);
+}
+
+/* If this enumeration is changed, getEncodingIndex and encodings
+must also be changed. */
+enum {
+  UNKNOWN_ENC = -1,
+  ISO_8859_1_ENC = 0,
+  US_ASCII_ENC,
+  UTF_8_ENC,
+  UTF_16_ENC,
+  UTF_16BE_ENC,
+  UTF_16LE_ENC,
+  /* must match encodingNames up to here */
+  NO_ENC
+};
+
+static const char KW_ISO_8859_1[] = {
+  ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0'
+};
+static const char KW_US_ASCII[] = {
+  ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, '\0'
+};
+static const char KW_UTF_8[] = {
+  ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'
+};
+static const char KW_UTF_16[] =        {
+  ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'
+};
+static const char KW_UTF_16BE[] = {
+  ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, '\0'
+};
+static const char KW_UTF_16LE[] = {
+  ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, '\0'
+};
+
+static
+int getEncodingIndex(const char *name)
+{
+  static const char *encodingNames[] = {
+    KW_ISO_8859_1,
+    KW_US_ASCII,
+    KW_UTF_8,
+    KW_UTF_16,
+    KW_UTF_16BE,
+    KW_UTF_16LE,
+  };
+  int i;
+  if (name == 0)
+    return NO_ENC;
+  for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++)
+    if (streqci(name, encodingNames[i]))
+      return i;
+  return UNKNOWN_ENC;
+}
+
+/* For binary compatibility, we store the index of the encoding specified
+at initialization in the isUtf16 member. */
+
+#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
+#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i)
+
+/* This is what detects the encoding.
+encodingTable maps from encoding indices to encodings;
+INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding;
+state is XML_CONTENT_STATE if we're parsing an external text entity,
+and XML_PROLOG_STATE otherwise.
+*/
+
+
+static
+int initScan(const ENCODING **encodingTable,
+            const INIT_ENCODING *enc,
+            int state,
+            const char *ptr,
+            const char *end,
+            const char **nextTokPtr)
+{
+  const ENCODING **encPtr;
+
+  if (ptr == end)
+    return XML_TOK_NONE;
+  encPtr = enc->encPtr;
+  if (ptr + 1 == end) {
+    /* only a single byte available for auto-detection */
+#ifndef XML_DTD /* FIXME */
+    /* a well-formed document entity must have more than one byte */
+    if (state != XML_CONTENT_STATE)
+      return XML_TOK_PARTIAL;
+#endif
+    /* so we're parsing an external text entity... */
+    /* if UTF-16 was externally specified, then we need at least 2 bytes */
+    switch (INIT_ENC_INDEX(enc)) {
+    case UTF_16_ENC:
+    case UTF_16LE_ENC:
+    case UTF_16BE_ENC:
+      return XML_TOK_PARTIAL;
+    }
+    switch ((unsigned char)*ptr) {
+    case 0xFE:
+    case 0xFF:
+    case 0xEF: /* possibly first byte of UTF-8 BOM */
+      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+         && state == XML_CONTENT_STATE)
+       break;
+      /* fall through */
+    case 0x00:
+    case 0x3C:
+      return XML_TOK_PARTIAL;
+    }
+  }
+  else {
+    switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
+    case 0xFEFF:
+      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+         && state == XML_CONTENT_STATE)
+       break;
+      *nextTokPtr = ptr + 2;
+      *encPtr = encodingTable[UTF_16BE_ENC];
+      return XML_TOK_BOM;
+    /* 00 3C is handled in the default case */
+    case 0x3C00:
+      if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
+          || INIT_ENC_INDEX(enc) == UTF_16_ENC)
+         && state == XML_CONTENT_STATE)
+       break;
+      *encPtr = encodingTable[UTF_16LE_ENC];
+      return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+    case 0xFFFE:
+      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+         && state == XML_CONTENT_STATE)
+       break;
+      *nextTokPtr = ptr + 2;
+      *encPtr = encodingTable[UTF_16LE_ENC];
+      return XML_TOK_BOM;
+    case 0xEFBB:
+      /* Maybe a UTF-8 BOM (EF BB BF) */
+      /* If there's an explicitly specified (external) encoding
+         of ISO-8859-1 or some flavour of UTF-16
+         and this is an external text entity,
+        don't look for the BOM,
+         because it might be a legal data. */
+      if (state == XML_CONTENT_STATE) {
+       int e = INIT_ENC_INDEX(enc);
+       if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC)
+         break;
+      }
+      if (ptr + 2 == end)
+       return XML_TOK_PARTIAL;
+      if ((unsigned char)ptr[2] == 0xBF) {
+       *encPtr = encodingTable[UTF_8_ENC];
+       return XML_TOK_BOM;
+      }
+      break;
+    default:
+      if (ptr[0] == '\0') {
+       /* 0 isn't a legal data character. Furthermore a document entity can only
+          start with ASCII characters.  So the only way this can fail to be big-endian
+          UTF-16 if it it's an external parsed general entity that's labelled as
+          UTF-16LE. */
+       if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
+         break;
+       *encPtr = encodingTable[UTF_16BE_ENC];
+       return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+      }
+      else if (ptr[1] == '\0') {
+       /* We could recover here in the case:
+           - parsing an external entity
+           - second byte is 0
+           - no externally specified encoding
+           - no encoding declaration
+          by assuming UTF-16LE.  But we don't, because this would mean when
+          presented just with a single byte, we couldn't reliably determine
+          whether we needed further bytes. */
+       if (state == XML_CONTENT_STATE)
+         break;
+       *encPtr = encodingTable[UTF_16LE_ENC];
+       return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+      }
+      break;
+    }
+  }
+  *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
+  return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+}
+
+
+#define NS(x) x
+#define ns(x) x
+#include "xmltok_ns.c"
+#undef NS
+#undef ns
+
+#ifdef XML_NS
+
+#define NS(x) x ## NS
+#define ns(x) x ## _ns
+
+#include "xmltok_ns.c"
+
+#undef NS
+#undef ns
+
+ENCODING *
+xmlrpc_XmlInitUnknownEncodingNS(void *mem,
+                        int *table,
+                        int (*convert)(void *userData, const char *p),
+                        void *userData)
+{
+  ENCODING *enc = xmlrpc_XmlInitUnknownEncoding(mem, table, convert, userData);
+  if (enc)
+    ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
+  return enc;
+}
+
+#endif /* XML_NS */
diff --git a/lib/expat/xmltok/xmltok.dsp b/lib/expat/xmltok/xmltok.dsp
new file mode 100644 (file)
index 0000000..58a70ef
--- /dev/null
@@ -0,0 +1,259 @@
+# Microsoft Developer Studio Project File - Name="xmltok" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xmltok - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "xmltok.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "xmltok.mak" CFG="xmltok - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "xmltok - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmltok - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "xmltok - Win32 Release DLL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "xmltok - Win32 Debug DLL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "xmltok"
+# PROP Scc_LocalPath ".."
+
+!IF  "$(CFG)" == "xmltok - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\Release"
+# PROP BASE Intermediate_Dir ".\Release"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release\xmltok"
+# PROP Intermediate_Dir "Release\xmltok"
+# PROP Target_Dir "."
+LINK32=link.exe -lib
+MTL=midl.exe
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\.." /D "NDEBUG" /D "XML_NS" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\Debug"
+# PROP BASE Intermediate_Dir ".\Debug"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug\xmltok"
+# PROP Intermediate_Dir "Debug\xmltok"
+# PROP Target_Dir "."
+LINK32=link.exe -lib
+MTL=midl.exe
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Release DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\ReleaseDLL"
+# PROP BASE Intermediate_Dir ".\ReleaseDLL"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseDLL\xmltok"
+# PROP Intermediate_Dir "ReleaseDLL\xmltok"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\.." /D "NDEBUG" /D "XML_NS" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"DllMain" /subsystem:windows /dll /machine:I386 /out:"..\..\xmltok.dll" /link50compat
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Debug DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\DebugDLL"
+# PROP BASE Intermediate_Dir ".\DebugDLL"
+# PROP BASE Target_Dir "."
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugDLL\xmltok"
+# PROP Intermediate_Dir "DebugDLL\xmltok"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "."
+CPP=cl.exe
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /YX /FD /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"..\..\xmltokD.dll"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "xmltok - Win32 Release"
+# Name "xmltok - Win32 Debug"
+# Name "xmltok - Win32 Release DLL"
+# Name "xmltok - Win32 Debug DLL"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\dllmain.c
+
+!IF  "$(CFG)" == "xmltok - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Release DLL"
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Debug DLL"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\gennmtab\gennmtab.c
+
+!IF  "$(CFG)" == "xmltok - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Release DLL"
+
+!ELSEIF  "$(CFG)" == "xmltok - Win32 Debug DLL"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlrole.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok_impl.c
+# PROP BASE Exclude_From_Build 1
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok_ns.c
+# PROP Exclude_From_Build 1
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
+# Begin Source File
+
+SOURCE=.\asciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\latin1tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\nametab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\utf8tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmldef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlrole.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok_impl.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/lib/expat/xmltok/xmltok.h b/lib/expat/xmltok/xmltok.h
new file mode 100644 (file)
index 0000000..a5b4cef
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#ifndef XmlTok_INCLUDED
+#define XmlTok_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef XMLTOKAPI
+#define XMLTOKAPI /* as nothing */
+#endif
+
+/* The following token may be returned by XmlContentTok */
+#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of
+                                    illegal ]]> sequence */
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_NONE -4    /* The string to be scanned is empty */
+#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
+                                  might be part of CRLF sequence */ 
+#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
+#define XML_TOK_PARTIAL -1 /* only part of a token */
+#define XML_TOK_INVALID 0
+
+/* The following tokens are returned by XmlContentTok; some are also
+  returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */
+
+#define XML_TOK_START_TAG_WITH_ATTS 1
+#define XML_TOK_START_TAG_NO_ATTS 2
+#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
+#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
+#define XML_TOK_END_TAG 5
+#define XML_TOK_DATA_CHARS 6
+#define XML_TOK_DATA_NEWLINE 7
+#define XML_TOK_CDATA_SECT_OPEN 8
+#define XML_TOK_ENTITY_REF 9
+#define XML_TOK_CHAR_REF 10     /* numeric character reference */
+
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_PI 11      /* processing instruction */
+#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
+#define XML_TOK_COMMENT 13
+#define XML_TOK_BOM 14     /* Byte order mark */
+
+/* The following tokens are returned only by XmlPrologTok */
+#define XML_TOK_PROLOG_S 15
+#define XML_TOK_DECL_OPEN 16 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
+#define XML_TOK_NAME 18
+#define XML_TOK_NMTOKEN 19
+#define XML_TOK_POUND_NAME 20 /* #name */
+#define XML_TOK_OR 21 /* | */
+#define XML_TOK_PERCENT 22
+#define XML_TOK_OPEN_PAREN 23
+#define XML_TOK_CLOSE_PAREN 24
+#define XML_TOK_OPEN_BRACKET 25
+#define XML_TOK_CLOSE_BRACKET 26
+#define XML_TOK_LITERAL 27
+#define XML_TOK_PARAM_ENTITY_REF 28
+#define XML_TOK_INSTANCE_START 29
+
+/* The following occur only in element type declarations */
+#define XML_TOK_NAME_QUESTION 30 /* name? */
+#define XML_TOK_NAME_ASTERISK 31 /* name* */
+#define XML_TOK_NAME_PLUS 32 /* name+ */
+#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
+#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
+#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
+#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
+#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
+#define XML_TOK_COMMA 38
+
+/* The following token is returned only by XmlAttributeValueTok */
+#define XML_TOK_ATTRIBUTE_VALUE_S 39
+
+/* The following token is returned only by XmlCdataSectionTok */
+#define XML_TOK_CDATA_SECT_CLOSE 40
+
+/* With namespace processing this is returned by XmlPrologTok
+   for a name with a colon. */
+#define XML_TOK_PREFIXED_NAME 41
+
+#ifdef XML_DTD
+#define XML_TOK_IGNORE_SECT 42
+#endif /* XML_DTD */
+
+#ifdef XML_DTD
+#define XML_N_STATES 4
+#else /* not XML_DTD */
+#define XML_N_STATES 3
+#endif /* not XML_DTD */
+
+#define XML_PROLOG_STATE 0
+#define XML_CONTENT_STATE 1
+#define XML_CDATA_SECTION_STATE 2
+#ifdef XML_DTD
+#define XML_IGNORE_SECTION_STATE 3
+#endif /* XML_DTD */
+
+#define XML_N_LITERAL_TYPES 2
+#define XML_ATTRIBUTE_VALUE_LITERAL 0
+#define XML_ENTITY_VALUE_LITERAL 1
+
+/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
+#define XML_UTF8_ENCODE_MAX 4
+/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
+#define XML_UTF16_ENCODE_MAX 2
+
+typedef struct position {
+  /* first line and first column are 0 not 1 */
+  unsigned long lineNumber;
+  unsigned long columnNumber;
+} POSITION;
+
+typedef struct {
+  const char *name;
+  const char *valuePtr;
+  const char *valueEnd;
+  char normalized;
+} ATTRIBUTE;
+
+struct encoding;
+typedef struct encoding ENCODING;
+
+struct encoding {
+  int (*scanners[XML_N_STATES])(const ENCODING *,
+                               const char *,
+                               const char *,
+                               const char **);
+  int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *,
+                                             const char *,
+                                             const char *,
+                                             const char **);
+  int (*sameName)(const ENCODING *,
+                 const char *, const char *);
+  int (*nameMatchesAscii)(const ENCODING *,
+                         const char *, const char *, const char *);
+  int (*nameLength)(const ENCODING *, const char *);
+  const char *(*skipS)(const ENCODING *, const char *);
+  int (*getAtts)(const ENCODING *enc, const char *ptr,
+                int attsMax, ATTRIBUTE *atts);
+  int (*charRefNumber)(const ENCODING *enc, const char *ptr);
+  int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
+  void (*updatePosition)(const ENCODING *,
+                        const char *ptr,
+                        const char *end,
+                        POSITION *);
+  int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+                   const char **badPtr);
+  void (*utf8Convert)(const ENCODING *enc,
+                     const char **fromP,
+                     const char *fromLim,
+                     char **toP,
+                     const char *toLim);
+  void (*utf16Convert)(const ENCODING *enc,
+                      const char **fromP,
+                      const char *fromLim,
+                      unsigned short **toP,
+                      const unsigned short *toLim);
+  int minBytesPerChar;
+  char isUtf8;
+  char isUtf16;
+};
+
+/*
+Scan the string starting at ptr until the end of the next complete token,
+but do not scan past eptr.  Return an integer giving the type of token.
+
+Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
+
+Return XML_TOK_PARTIAL when the string does not contain a complete token;
+nextTokPtr will not be set.
+
+Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr
+will be set to point to the character which made the token invalid.
+
+Otherwise the string starts with a valid token; nextTokPtr will be set to point
+to the character following the end of that token.
+
+Each data character counts as a single token, but adjacent data characters
+may be returned together.  Similarly for characters in the prolog outside
+literals, comments and processing instructions.
+*/
+
+
+#define XmlTok(enc, state, ptr, end, nextTokPtr) \
+  (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
+
+#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
+   XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
+
+#define XmlContentTok(enc, ptr, end, nextTokPtr) \
+   XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
+
+#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
+   XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
+
+#ifdef XML_DTD
+
+#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
+   XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
+
+#endif /* XML_DTD */
+
+/* This is used for performing a 2nd-level tokenization on
+the content of a literal that has already been returned by XmlTok. */ 
+
+#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
+  (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
+
+#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
+   XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
+   XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
+
+#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
+  (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
+
+#define XmlNameLength(enc, ptr) \
+  (((enc)->nameLength)(enc, ptr))
+
+#define XmlSkipS(enc, ptr) \
+  (((enc)->skipS)(enc, ptr))
+
+#define XmlGetAttributes(enc, ptr, attsMax, atts) \
+  (((enc)->getAtts)(enc, ptr, attsMax, atts))
+
+#define XmlCharRefNumber(enc, ptr) \
+  (((enc)->charRefNumber)(enc, ptr))
+
+#define XmlPredefinedEntityName(enc, ptr, end) \
+  (((enc)->predefinedEntityName)(enc, ptr, end))
+
+#define XmlUpdatePosition(enc, ptr, end, pos) \
+  (((enc)->updatePosition)(enc, ptr, end, pos))
+
+#define XmlIsPublicId(enc, ptr, end, badPtr) \
+  (((enc)->isPublicId)(enc, ptr, end, badPtr))
+
+#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
+  (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
+
+#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
+  (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
+
+typedef struct {
+  ENCODING initEnc;
+  const ENCODING **encPtr;
+} INIT_ENCODING;
+
+int XMLTOKAPI 
+xmlrpc_XmlParseXmlDecl(int               isGeneralTextEntity,
+                       const ENCODING *  enc,
+                       const char *      ptr,
+                       const char *      end,
+                       const char **     badPtr,
+                       const char **     versionPtr,
+                       const char **     encodingNamePtr,
+                       const ENCODING ** namedEncodingPtr,
+                       int *             standalonePtr);
+
+int 
+XMLTOKAPI
+xmlrpc_XmlInitEncoding(INIT_ENCODING *,
+                       const ENCODING **,
+                       const char * name);
+
+const ENCODING XMLTOKAPI *
+xmlrpc_XmlGetUtf8InternalEncoding(void);
+
+const ENCODING XMLTOKAPI *
+xmlrpc_XmlGetUtf16InternalEncoding(void);
+
+int XMLTOKAPI
+xmlrpc_XmlUtf8Encode(int charNumber, char *buf);
+
+int XMLTOKAPI 
+xmlrpc_XmlUtf16Encode(int              charNumber,
+                      unsigned short * buf);
+
+int XMLTOKAPI
+xmlrpc_XmlSizeOfUnknownEncoding(void);
+
+ENCODING XMLTOKAPI *
+xmlrpc_XmlInitUnknownEncoding(void * mem,
+                              int *  table,
+                              int (* conv)(void * userData, const char * p),
+                              void * userData);
+
+int XMLTOKAPI
+xmlrpc_XmlParseXmlDeclNS(int               isGeneralTextEntity,
+                         const ENCODING *  enc,
+                         const char *      ptr,
+                         const char *      end,
+                         const char **     badPtr,
+                         const char **     versionPtr,
+                         const char **     encodingNamePtr,
+                         const ENCODING ** namedEncodingPtr,
+                         int *             standalonePtr);
+
+int XMLTOKAPI
+xmlrpc_XmlInitEncodingNS(INIT_ENCODING *,
+                         const ENCODING **,
+                         const char * name);
+
+const ENCODING XMLTOKAPI *
+xmlrpc_XmlGetUtf8InternalEncodingNS(void);
+
+const ENCODING XMLTOKAPI *
+xmlrpc_XmlGetUtf16InternalEncodingNS(void);
+
+ENCODING XMLTOKAPI *
+xmlrpc_XmlInitUnknownEncodingNS(void * mem,
+                                int *  table,
+                                int (* conv)(void * userData, const char * p),
+                                void * userData);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlTok_INCLUDED */
diff --git a/lib/expat/xmltok/xmltok_impl.c b/lib/expat/xmltok/xmltok_impl.c
new file mode 100644 (file)
index 0000000..0ebb945
--- /dev/null
@@ -0,0 +1,1774 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#ifndef IS_INVALID_CHAR
+#define IS_INVALID_CHAR(enc, ptr, n) (0)
+#endif
+
+#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
+    case BT_LEAD ## n: \
+      if (end - ptr < n) \
+       return XML_TOK_PARTIAL_CHAR; \
+      if (IS_INVALID_CHAR(enc, ptr, n)) { \
+        *(nextTokPtr) = (ptr); \
+        return XML_TOK_INVALID; \
+      } \
+      ptr += n; \
+      break;
+
+#define INVALID_CASES(ptr, nextTokPtr) \
+  INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
+  INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
+  INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
+  case BT_NONXML: \
+  case BT_MALFORM: \
+  case BT_TRAIL: \
+    *(nextTokPtr) = (ptr); \
+    return XML_TOK_INVALID;
+
+#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
+   case BT_LEAD ## n: \
+     if (end - ptr < n) \
+       return XML_TOK_PARTIAL_CHAR; \
+     if (!IS_NAME_CHAR(enc, ptr, n)) { \
+       *nextTokPtr = ptr; \
+       return XML_TOK_INVALID; \
+     } \
+     ptr += n; \
+     break;
+
+#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
+  case BT_NONASCII: \
+    if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
+      *nextTokPtr = ptr; \
+      return XML_TOK_INVALID; \
+    } \
+  case BT_NMSTRT: \
+  case BT_HEX: \
+  case BT_DIGIT: \
+  case BT_NAME: \
+  case BT_MINUS: \
+    ptr += MINBPC(enc); \
+    break; \
+  CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
+  CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
+  CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
+
+#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
+   case BT_LEAD ## n: \
+     if (end - ptr < n) \
+       return XML_TOK_PARTIAL_CHAR; \
+     if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
+       *nextTokPtr = ptr; \
+       return XML_TOK_INVALID; \
+     } \
+     ptr += n; \
+     break;
+
+#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
+  case BT_NONASCII: \
+    if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
+      *nextTokPtr = ptr; \
+      return XML_TOK_INVALID; \
+    } \
+  case BT_NMSTRT: \
+  case BT_HEX: \
+    ptr += MINBPC(enc); \
+    break; \
+  CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
+  CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
+  CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
+
+#ifndef PREFIX
+#define PREFIX(ident) ident
+#endif
+
+/* ptr points to character following "<!-" */
+
+static
+int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
+                       const char **nextTokPtr)
+{
+  if (ptr != end) {
+    if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+    ptr += MINBPC(enc);
+    while (ptr != end) {
+      switch (BYTE_TYPE(enc, ptr)) {
+      INVALID_CASES(ptr, nextTokPtr)
+      case BT_MINUS:
+       if ((ptr += MINBPC(enc)) == end)
+         return XML_TOK_PARTIAL;
+       if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+         if ((ptr += MINBPC(enc)) == end)
+           return XML_TOK_PARTIAL;
+         if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+           *nextTokPtr = ptr;
+           return XML_TOK_INVALID;
+         }
+         *nextTokPtr = ptr + MINBPC(enc);
+         return XML_TOK_COMMENT;
+       }
+       break;
+      default:
+       ptr += MINBPC(enc);
+       break;
+      }
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<!" */
+
+static
+int PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
+                    const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  case BT_MINUS:
+    return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_LSQB:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_COND_SECT_OPEN;
+  case BT_NMSTRT:
+  case BT_HEX:
+    ptr += MINBPC(enc);
+    break;
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_PERCNT:
+      if (ptr + MINBPC(enc) == end)
+       return XML_TOK_PARTIAL;
+      /* don't allow <!ENTITY% foo "whatever"> */
+      switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
+      case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      /* fall through */
+    case BT_S: case BT_CR: case BT_LF:
+      *nextTokPtr = ptr;
+      return XML_TOK_DECL_OPEN;
+    case BT_NMSTRT:
+    case BT_HEX:
+      ptr += MINBPC(enc);
+      break;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(checkPiTarget)(const ENCODING * enc ATTR_UNUSED, 
+                          const char *     ptr, 
+                          const char *     end, 
+                          int *            tokPtr)
+{
+  int upper = 0;
+  *tokPtr = XML_TOK_PI;
+  if (end - ptr != MINBPC(enc)*3)
+    return 1;
+  switch (BYTE_TO_ASCII(enc, ptr)) {
+  case ASCII_x:
+    break;
+  case ASCII_X:
+    upper = 1;
+    break;
+  default:
+    return 1;
+  }
+  ptr += MINBPC(enc);
+  switch (BYTE_TO_ASCII(enc, ptr)) {
+  case ASCII_m:
+    break;
+  case ASCII_M:
+    upper = 1;
+    break;
+  default:
+    return 1;
+  }
+  ptr += MINBPC(enc);
+  switch (BYTE_TO_ASCII(enc, ptr)) {
+  case ASCII_l:
+    break;
+  case ASCII_L:
+    upper = 1;
+    break;
+  default:
+    return 1;
+  }
+  if (upper)
+    return 0;
+  *tokPtr = XML_TOK_XML_DECL;
+  return 1;
+}
+
+/* ptr points to character following "<?" */
+
+static
+int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
+                  const char **nextTokPtr)
+{
+  int tok;
+  const char *target = ptr;
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_S: case BT_CR: case BT_LF:
+      if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      ptr += MINBPC(enc);
+      while (ptr != end) {
+        switch (BYTE_TYPE(enc, ptr)) {
+        INVALID_CASES(ptr, nextTokPtr)
+       case BT_QUEST:
+         ptr += MINBPC(enc);
+         if (ptr == end)
+           return XML_TOK_PARTIAL;
+         if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+           *nextTokPtr = ptr + MINBPC(enc);
+           return tok;
+         }
+         break;
+       default:
+         ptr += MINBPC(enc);
+         break;
+       }
+      }
+      return XML_TOK_PARTIAL;
+    case BT_QUEST:
+      if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      ptr += MINBPC(enc);
+      if (ptr == end)
+       return XML_TOK_PARTIAL;
+      if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+       *nextTokPtr = ptr + MINBPC(enc);
+       return tok;
+      }
+      /* fall through */
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+
+static
+int PREFIX(scanCdataSection)(const ENCODING * enc ATTR_UNUSED, 
+                             const char *     ptr, 
+                             const char *     end,
+                             const char **    nextTokPtr)
+{
+  static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, ASCII_LSQB };
+  int i;
+  /* CDATA[ */
+  if (end - ptr < 6 * MINBPC(enc))
+    return XML_TOK_PARTIAL;
+  for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
+    if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_CDATA_SECT_OPEN;
+}
+
+static
+int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+                           const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_NONE;
+  if (MINBPC(enc) > 1) {
+    size_t n = end - ptr;
+    if (n & (MINBPC(enc) - 1)) {
+      n &= ~(MINBPC(enc) - 1);
+      if (n == 0)
+       return XML_TOK_PARTIAL;
+      end = ptr + n;
+    }
+  }
+  switch (BYTE_TYPE(enc, ptr)) {
+  case BT_RSQB:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_PARTIAL;
+    if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+      break;
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_PARTIAL;
+    if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+      ptr -= MINBPC(enc);
+      break;
+    }
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_CDATA_SECT_CLOSE;
+  case BT_CR:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_PARTIAL;
+    if (BYTE_TYPE(enc, ptr) == BT_LF)
+      ptr += MINBPC(enc);
+    *nextTokPtr = ptr;
+    return XML_TOK_DATA_NEWLINE;
+  case BT_LF:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_DATA_NEWLINE;
+  INVALID_CASES(ptr, nextTokPtr)
+  default:
+    ptr += MINBPC(enc);
+    break;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: \
+      if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+       *nextTokPtr = ptr; \
+       return XML_TOK_DATA_CHARS; \
+      } \
+      ptr += n; \
+      break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_NONXML:
+    case BT_MALFORM:
+    case BT_TRAIL:
+    case BT_CR:
+    case BT_LF:
+    case BT_RSQB:
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "</" */
+
+static
+int PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
+                      const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_S: case BT_CR: case BT_LF:
+      for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+       switch (BYTE_TYPE(enc, ptr)) {
+       case BT_S: case BT_CR: case BT_LF:
+         break;
+       case BT_GT:
+         *nextTokPtr = ptr + MINBPC(enc);
+          return XML_TOK_END_TAG;
+       default:
+         *nextTokPtr = ptr;
+         return XML_TOK_INVALID;
+       }
+      }
+      return XML_TOK_PARTIAL;
+#ifdef XML_NS
+    case BT_COLON:
+      /* no need to check qname syntax here, since end-tag must match exactly */
+      ptr += MINBPC(enc);
+      break;
+#endif
+    case BT_GT:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_END_TAG;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#X" */
+
+static
+int PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+                          const char **nextTokPtr)
+{
+  if (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_DIGIT:
+    case BT_HEX:
+      break;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+    for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_DIGIT:
+      case BT_HEX:
+       break;
+      case BT_SEMI:
+       *nextTokPtr = ptr + MINBPC(enc);
+       return XML_TOK_CHAR_REF;
+      default:
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#" */
+
+static
+int PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+                       const char **nextTokPtr)
+{
+  if (ptr != end) {
+    if (CHAR_MATCHES(enc, ptr, ASCII_x))
+      return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_DIGIT:
+      break;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+    for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_DIGIT:
+       break;
+      case BT_SEMI:
+       *nextTokPtr = ptr + MINBPC(enc);
+       return XML_TOK_CHAR_REF;
+      default:
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&" */
+
+static
+int PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
+                   const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  case BT_NUM:
+    return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_SEMI:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_ENTITY_REF;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following first character of attribute name */
+
+static
+int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+                    const char **nextTokPtr)
+{
+#ifdef XML_NS
+  int hadColon = 0;
+#endif
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+    case BT_COLON:
+      if (hadColon) {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      hadColon = 1;
+      ptr += MINBPC(enc);
+      if (ptr == end)
+       return XML_TOK_PARTIAL;
+      switch (BYTE_TYPE(enc, ptr)) {
+      CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+      default:
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      break;
+#endif
+    case BT_S: case BT_CR: case BT_LF:
+      for (;;) {
+       int t;
+
+       ptr += MINBPC(enc);
+       if (ptr == end)
+         return XML_TOK_PARTIAL;
+       t = BYTE_TYPE(enc, ptr);
+       if (t == BT_EQUALS)
+         break;
+       switch (t) {
+       case BT_S:
+       case BT_LF:
+       case BT_CR:
+         break;
+       default:
+         *nextTokPtr = ptr;
+         return XML_TOK_INVALID;
+       }
+      }
+    /* fall through */
+    case BT_EQUALS:
+      {
+       int open;
+#ifdef XML_NS
+       hadColon = 0;
+#endif
+       for (;;) {
+         
+         ptr += MINBPC(enc);
+         if (ptr == end)
+           return XML_TOK_PARTIAL;
+         open = BYTE_TYPE(enc, ptr);
+         if (open == BT_QUOT || open == BT_APOS)
+           break;
+         switch (open) {
+         case BT_S:
+         case BT_LF:
+         case BT_CR:
+           break;
+         default:
+           *nextTokPtr = ptr;
+           return XML_TOK_INVALID;
+         }
+       }
+       ptr += MINBPC(enc);
+       /* in attribute value */
+       for (;;) {
+         int t;
+         if (ptr == end)
+           return XML_TOK_PARTIAL;
+         t = BYTE_TYPE(enc, ptr);
+         if (t == open)
+           break;
+         switch (t) {
+         INVALID_CASES(ptr, nextTokPtr)
+         case BT_AMP:
+           {
+             int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+             if (tok <= 0) {
+               if (tok == XML_TOK_INVALID)
+                 *nextTokPtr = ptr;
+               return tok;
+             }
+             break;
+           }
+         case BT_LT:
+           *nextTokPtr = ptr;
+           return XML_TOK_INVALID;
+         default:
+           ptr += MINBPC(enc);
+           break;
+         }
+       }
+       ptr += MINBPC(enc);
+       if (ptr == end)
+         return XML_TOK_PARTIAL;
+       switch (BYTE_TYPE(enc, ptr)) {
+       case BT_S:
+       case BT_CR:
+       case BT_LF:
+         break;
+       case BT_SOL:
+         goto sol;
+       case BT_GT:
+         goto gt;
+       default:
+         *nextTokPtr = ptr;
+         return XML_TOK_INVALID;
+       }
+       /* ptr points to closing quote */
+       for (;;) {
+         ptr += MINBPC(enc);
+         if (ptr == end)
+           return XML_TOK_PARTIAL;
+         switch (BYTE_TYPE(enc, ptr)) {
+         CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+         case BT_S: case BT_CR: case BT_LF:
+           continue;
+         case BT_GT:
+          gt:
+           *nextTokPtr = ptr + MINBPC(enc);
+           return XML_TOK_START_TAG_WITH_ATTS;
+         case BT_SOL:
+          sol:
+           ptr += MINBPC(enc);
+           if (ptr == end)
+             return XML_TOK_PARTIAL;
+           if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+             *nextTokPtr = ptr;
+             return XML_TOK_INVALID;
+           }
+           *nextTokPtr = ptr + MINBPC(enc);
+           return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+         default:
+           *nextTokPtr = ptr;
+           return XML_TOK_INVALID;
+         }
+         break;
+       }
+       break;
+      }
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<" */
+
+static
+int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+                  const char **nextTokPtr)
+{
+#ifdef XML_NS
+  int hadColon;
+#endif
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  case BT_EXCL:
+    if ((ptr += MINBPC(enc)) == end)
+      return XML_TOK_PARTIAL;
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_MINUS:
+      return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+    case BT_LSQB:
+      return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  case BT_QUEST:
+    return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_SOL:
+    return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+#ifdef XML_NS
+  hadColon = 0;
+#endif
+  /* we have a start-tag */
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+    case BT_COLON:
+      if (hadColon) {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      hadColon = 1;
+      ptr += MINBPC(enc);
+      if (ptr == end)
+       return XML_TOK_PARTIAL;
+      switch (BYTE_TYPE(enc, ptr)) {
+      CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+      default:
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      break;
+#endif
+    case BT_S: case BT_CR: case BT_LF:
+      {
+        ptr += MINBPC(enc);
+       while (ptr != end) {
+         switch (BYTE_TYPE(enc, ptr)) {
+         CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+         case BT_GT:
+           goto gt;
+         case BT_SOL:
+           goto sol;
+         case BT_S: case BT_CR: case BT_LF:
+           ptr += MINBPC(enc);
+           continue;
+         default:
+           *nextTokPtr = ptr;
+           return XML_TOK_INVALID;
+         }
+         return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+       }
+       return XML_TOK_PARTIAL;
+      }
+    case BT_GT:
+    gt:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_START_TAG_NO_ATTS;
+    case BT_SOL:
+    sol:
+      ptr += MINBPC(enc);
+      if (ptr == end)
+       return XML_TOK_PARTIAL;
+      if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+                      const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_NONE;
+  if (MINBPC(enc) > 1) {
+    size_t n = end - ptr;
+    if (n & (MINBPC(enc) - 1)) {
+      n &= ~(MINBPC(enc) - 1);
+      if (n == 0)
+       return XML_TOK_PARTIAL;
+      end = ptr + n;
+    }
+  }
+  switch (BYTE_TYPE(enc, ptr)) {
+  case BT_LT:
+    return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_AMP:
+    return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_CR:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_TRAILING_CR;
+    if (BYTE_TYPE(enc, ptr) == BT_LF)
+      ptr += MINBPC(enc);
+    *nextTokPtr = ptr;
+    return XML_TOK_DATA_NEWLINE;
+  case BT_LF:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_DATA_NEWLINE;
+  case BT_RSQB:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_TRAILING_RSQB;
+    if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+      break;
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_TRAILING_RSQB;
+    if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+      ptr -= MINBPC(enc);
+      break;
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  INVALID_CASES(ptr, nextTokPtr)
+  default:
+    ptr += MINBPC(enc);
+    break;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: \
+      if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+       *nextTokPtr = ptr; \
+       return XML_TOK_DATA_CHARS; \
+      } \
+      ptr += n; \
+      break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_RSQB:
+      if (ptr + MINBPC(enc) != end) {
+        if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
+          ptr += MINBPC(enc);
+          break;
+        }
+        if (ptr + 2*MINBPC(enc) != end) {
+          if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) {
+            ptr += MINBPC(enc);
+            break;
+          }
+          *nextTokPtr = ptr + 2*MINBPC(enc);
+          return XML_TOK_INVALID;
+        }
+      }
+      /* fall through */
+    case BT_AMP:
+    case BT_LT:
+    case BT_NONXML:
+    case BT_MALFORM:
+    case BT_TRAIL:
+    case BT_CR:
+    case BT_LF:
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "%" */
+
+static
+int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
+                       const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
+    *nextTokPtr = ptr;
+    return XML_TOK_PERCENT;
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_SEMI:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_PARAM_ENTITY_REF;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
+                         const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_CR: case BT_LF: case BT_S:
+    case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
+      *nextTokPtr = ptr;
+      return XML_TOK_POUND_NAME;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return -XML_TOK_POUND_NAME;
+}
+
+static
+int PREFIX(scanLit)(int open, const ENCODING *enc,
+                   const char *ptr, const char *end,
+                   const char **nextTokPtr)
+{
+  while (ptr != end) {
+    int t = BYTE_TYPE(enc, ptr);
+    switch (t) {
+    INVALID_CASES(ptr, nextTokPtr)
+    case BT_QUOT:
+    case BT_APOS:
+      ptr += MINBPC(enc);
+      if (t != open)
+       break;
+      if (ptr == end)
+       return -XML_TOK_LITERAL;
+      *nextTokPtr = ptr;
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_S: case BT_CR: case BT_LF:
+      case BT_GT: case BT_PERCNT: case BT_LSQB:
+       return XML_TOK_LITERAL;
+      default:
+       return XML_TOK_INVALID;
+      }
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+                     const char **nextTokPtr)
+{
+  int tok;
+  if (ptr == end)
+    return XML_TOK_NONE;
+  if (MINBPC(enc) > 1) {
+    size_t n = end - ptr;
+    if (n & (MINBPC(enc) - 1)) {
+      n &= ~(MINBPC(enc) - 1);
+      if (n == 0)
+       return XML_TOK_PARTIAL;
+      end = ptr + n;
+    }
+  }
+  switch (BYTE_TYPE(enc, ptr)) {
+  case BT_QUOT:
+    return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_APOS:
+    return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_LT:
+    {
+      ptr += MINBPC(enc);
+      if (ptr == end)
+       return XML_TOK_PARTIAL;
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_EXCL:
+       return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      case BT_QUEST:
+       return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      case BT_NMSTRT:
+      case BT_HEX:
+      case BT_NONASCII:
+      case BT_LEAD2:
+      case BT_LEAD3:
+      case BT_LEAD4:
+       *nextTokPtr = ptr - MINBPC(enc);
+       return XML_TOK_INSTANCE_START;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  case BT_CR:
+    if (ptr + MINBPC(enc) == end)
+      return -XML_TOK_PROLOG_S;
+    /* fall through */
+  case BT_S: case BT_LF:
+    for (;;) {
+      ptr += MINBPC(enc);
+      if (ptr == end)
+       break;
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_S: case BT_LF:
+       break;
+      case BT_CR:
+       /* don't split CR/LF pair */
+       if (ptr + MINBPC(enc) != end)
+         break;
+       /* fall through */
+      default:
+       *nextTokPtr = ptr;
+       return XML_TOK_PROLOG_S;
+      }
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_PROLOG_S;
+  case BT_PERCNT:
+    return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_COMMA:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_COMMA;
+  case BT_LSQB:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_OPEN_BRACKET;
+  case BT_RSQB:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return -XML_TOK_CLOSE_BRACKET;
+    if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+      if (ptr + MINBPC(enc) == end)
+       return XML_TOK_PARTIAL;
+      if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) {
+       *nextTokPtr = ptr + 2*MINBPC(enc);
+       return XML_TOK_COND_SECT_CLOSE;
+      }
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_CLOSE_BRACKET;
+  case BT_LPAR:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_OPEN_PAREN;
+  case BT_RPAR:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return -XML_TOK_CLOSE_PAREN;
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_AST:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_CLOSE_PAREN_ASTERISK;
+    case BT_QUEST:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_CLOSE_PAREN_QUESTION;
+    case BT_PLUS:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_CLOSE_PAREN_PLUS;
+    case BT_CR: case BT_LF: case BT_S:
+    case BT_GT: case BT_COMMA: case BT_VERBAR:
+    case BT_RPAR:
+      *nextTokPtr = ptr;
+      return XML_TOK_CLOSE_PAREN;
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  case BT_VERBAR:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_OR;
+  case BT_GT:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_DECL_CLOSE;
+  case BT_NUM:
+    return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+#define LEAD_CASE(n) \
+  case BT_LEAD ## n: \
+    if (end - ptr < n) \
+      return XML_TOK_PARTIAL_CHAR; \
+    if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
+      ptr += n; \
+      tok = XML_TOK_NAME; \
+      break; \
+    } \
+    if (IS_NAME_CHAR(enc, ptr, n)) { \
+      ptr += n; \
+      tok = XML_TOK_NMTOKEN; \
+      break; \
+    } \
+    *nextTokPtr = ptr; \
+    return XML_TOK_INVALID;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+  case BT_NMSTRT:
+  case BT_HEX:
+    tok = XML_TOK_NAME;
+    ptr += MINBPC(enc);
+    break;
+  case BT_DIGIT:
+  case BT_NAME:
+  case BT_MINUS:
+#ifdef XML_NS
+  case BT_COLON:
+#endif
+    tok = XML_TOK_NMTOKEN;
+    ptr += MINBPC(enc);
+    break;
+  case BT_NONASCII:
+    if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
+      ptr += MINBPC(enc);
+      tok = XML_TOK_NAME;
+      break;
+    }
+    if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
+      ptr += MINBPC(enc);
+      tok = XML_TOK_NMTOKEN;
+      break;
+    }
+    /* fall through */
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_GT: case BT_RPAR: case BT_COMMA:
+    case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
+    case BT_S: case BT_CR: case BT_LF:
+      *nextTokPtr = ptr;
+      return tok;
+#ifdef XML_NS
+    case BT_COLON:
+      ptr += MINBPC(enc);
+      switch (tok) {
+      case XML_TOK_NAME:
+       if (ptr == end)
+         return XML_TOK_PARTIAL;
+       tok = XML_TOK_PREFIXED_NAME;
+       switch (BYTE_TYPE(enc, ptr)) {
+       CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+       default:
+         tok = XML_TOK_NMTOKEN;
+         break;
+       }
+       break;
+      case XML_TOK_PREFIXED_NAME:
+       tok = XML_TOK_NMTOKEN;
+       break;
+      }
+      break;
+#endif
+    case BT_PLUS:
+      if (tok == XML_TOK_NMTOKEN)  {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_NAME_PLUS;
+    case BT_AST:
+      if (tok == XML_TOK_NMTOKEN)  {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_NAME_ASTERISK;
+    case BT_QUEST:
+      if (tok == XML_TOK_NMTOKEN)  {
+       *nextTokPtr = ptr;
+       return XML_TOK_INVALID;
+      }
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_NAME_QUESTION;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return -tok;
+}
+
+static
+int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+                             const char **nextTokPtr)
+{
+  const char *start;
+  if (ptr == end)
+    return XML_TOK_NONE;
+  start = ptr;
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: ptr += n; break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_AMP:
+      if (ptr == start)
+       return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_LT:
+      /* this is for inside entity references */
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    case BT_LF:
+      if (ptr == start) {
+       *nextTokPtr = ptr + MINBPC(enc);
+       return XML_TOK_DATA_NEWLINE;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_CR:
+      if (ptr == start) {
+       ptr += MINBPC(enc);
+       if (ptr == end)
+         return XML_TOK_TRAILING_CR;
+       if (BYTE_TYPE(enc, ptr) == BT_LF)
+         ptr += MINBPC(enc);
+       *nextTokPtr = ptr;
+       return XML_TOK_DATA_NEWLINE;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_S:
+      if (ptr == start) {
+       *nextTokPtr = ptr + MINBPC(enc);
+       return XML_TOK_ATTRIBUTE_VALUE_S;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_DATA_CHARS;
+}
+
+static
+int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+                          const char **nextTokPtr)
+{
+  const char *start;
+  if (ptr == end)
+    return XML_TOK_NONE;
+  start = ptr;
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: ptr += n; break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_AMP:
+      if (ptr == start)
+       return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_PERCNT:
+      if (ptr == start)
+       return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_LF:
+      if (ptr == start) {
+       *nextTokPtr = ptr + MINBPC(enc);
+       return XML_TOK_DATA_NEWLINE;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_CR:
+      if (ptr == start) {
+       ptr += MINBPC(enc);
+       if (ptr == end)
+         return XML_TOK_TRAILING_CR;
+       if (BYTE_TYPE(enc, ptr) == BT_LF)
+         ptr += MINBPC(enc);
+       *nextTokPtr = ptr;
+       return XML_TOK_DATA_NEWLINE;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_DATA_CHARS;
+}
+
+#ifdef XML_DTD
+
+static
+int PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+                            const char **nextTokPtr)
+{
+  int level = 0;
+  if (MINBPC(enc) > 1) {
+    size_t n = end - ptr;
+    if (n & (MINBPC(enc) - 1)) {
+      n &= ~(MINBPC(enc) - 1);
+      end = ptr + n;
+    }
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    INVALID_CASES(ptr, nextTokPtr)
+    case BT_LT:
+      if ((ptr += MINBPC(enc)) == end)
+       return XML_TOK_PARTIAL;
+      if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) {
+       if ((ptr += MINBPC(enc)) == end)
+         return XML_TOK_PARTIAL;
+       if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) {
+         ++level;
+         ptr += MINBPC(enc);
+       }
+      }
+      break;
+    case BT_RSQB:
+      if ((ptr += MINBPC(enc)) == end)
+       return XML_TOK_PARTIAL;
+      if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+       if ((ptr += MINBPC(enc)) == end)
+         return XML_TOK_PARTIAL;
+       if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+         ptr += MINBPC(enc);
+         if (level == 0) {
+           *nextTokPtr = ptr;
+           return XML_TOK_IGNORE_SECT;
+         }
+         --level;
+       }
+      }
+      break;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+#endif /* XML_DTD */
+
+static
+int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+                      const char **badPtr)
+{
+  ptr += MINBPC(enc);
+  end -= MINBPC(enc);
+  for (; ptr != end; ptr += MINBPC(enc)) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_DIGIT:
+    case BT_HEX:
+    case BT_MINUS:
+    case BT_APOS:
+    case BT_LPAR:
+    case BT_RPAR:
+    case BT_PLUS:
+    case BT_COMMA:
+    case BT_SOL:
+    case BT_EQUALS:
+    case BT_QUEST:
+    case BT_CR:
+    case BT_LF:
+    case BT_SEMI:
+    case BT_EXCL:
+    case BT_AST:
+    case BT_PERCNT:
+    case BT_NUM:
+#ifdef XML_NS
+    case BT_COLON:
+#endif
+      break;
+    case BT_S:
+      if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
+       *badPtr = ptr;
+       return 0;
+      }
+      break;
+    case BT_NAME:
+    case BT_NMSTRT:
+      if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
+       break;
+    default:
+      switch (BYTE_TO_ASCII(enc, ptr)) {
+      case 0x24: /* $ */
+      case 0x40: /* @ */
+       break;
+      default:
+       *badPtr = ptr;
+       return 0;
+      }
+      break;
+    }
+  }
+  return 1;
+}
+
+/* This must only be called for a well-formed start-tag or empty element tag.
+Returns the number of attributes.  Pointers to the first attsMax attributes 
+are stored in atts. */
+
+static
+int PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
+                   int attsMax, ATTRIBUTE *atts)
+{
+  enum { other, inName, inValue } state = inName;
+  int nAtts = 0;
+  int open = 0; /* defined when state == inValue;
+                  initialization just to shut up compilers */
+
+  for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define START_NAME \
+      if (state == other) { \
+       if (nAtts < attsMax) { \
+         atts[nAtts].name = ptr; \
+         atts[nAtts].normalized = 1; \
+       } \
+       state = inName; \
+      }
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_NONASCII:
+    case BT_NMSTRT:
+    case BT_HEX:
+      START_NAME
+      break;
+#undef START_NAME
+    case BT_QUOT:
+      if (state != inValue) {
+       if (nAtts < attsMax)
+         atts[nAtts].valuePtr = ptr + MINBPC(enc);
+        state = inValue;
+        open = BT_QUOT;
+      }
+      else if (open == BT_QUOT) {
+        state = other;
+       if (nAtts < attsMax)
+         atts[nAtts].valueEnd = ptr;
+       nAtts++;
+      }
+      break;
+    case BT_APOS:
+      if (state != inValue) {
+       if (nAtts < attsMax)
+         atts[nAtts].valuePtr = ptr + MINBPC(enc);
+        state = inValue;
+        open = BT_APOS;
+      }
+      else if (open == BT_APOS) {
+        state = other;
+       if (nAtts < attsMax)
+         atts[nAtts].valueEnd = ptr;
+       nAtts++;
+      }
+      break;
+    case BT_AMP:
+      if (nAtts < attsMax)
+       atts[nAtts].normalized = 0;
+      break;
+    case BT_S:
+      if (state == inName)
+        state = other;
+      else if (state == inValue
+              && nAtts < attsMax
+              && atts[nAtts].normalized
+              && (ptr == atts[nAtts].valuePtr
+                  || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE
+                  || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE
+                  || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
+       atts[nAtts].normalized = 0;
+      break;
+    case BT_CR: case BT_LF:
+      /* This case ensures that the first attribute name is counted
+         Apart from that we could just change state on the quote. */
+      if (state == inName)
+        state = other;
+      else if (state == inValue && nAtts < attsMax)
+       atts[nAtts].normalized = 0;
+      break;
+    case BT_GT:
+    case BT_SOL:
+      if (state != inValue)
+       return nAtts;
+      break;
+    default:
+      break;
+    }
+  }
+  /* not reached */
+}
+
+static
+int PREFIX(charRefNumber)(const ENCODING *enc ATTR_UNUSED, const char *ptr)
+{
+  int result = 0;
+  /* skip &# */
+  ptr += 2*MINBPC(enc);
+  if (CHAR_MATCHES(enc, ptr, ASCII_x)) {
+    for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+      int c = BYTE_TO_ASCII(enc, ptr);
+      switch (c) {
+      case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4:
+      case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9:
+       result <<= 4;
+       result |= (c - ASCII_0);
+       break;
+      case ASCII_A: case ASCII_B: case ASCII_C: case ASCII_D: case ASCII_E: case ASCII_F:
+       result <<= 4;
+       result += 10 + (c - ASCII_A);
+       break;
+      case ASCII_a: case ASCII_b: case ASCII_c: case ASCII_d: case ASCII_e: case ASCII_f:
+       result <<= 4;
+       result += 10 + (c - ASCII_a);
+       break;
+      }
+      if (result >= 0x110000)
+       return -1;
+    }
+  }
+  else {
+    for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+      int c = BYTE_TO_ASCII(enc, ptr);
+      result *= 10;
+      result += (c - ASCII_0);
+      if (result >= 0x110000)
+       return -1;
+    }
+  }
+  return checkCharRefNumber(result);
+}
+
+static
+int PREFIX(predefinedEntityName)(const ENCODING * enc ATTR_UNUSED, 
+                                 const char *     ptr, 
+                                 const char *     end)
+{
+  switch ((end - ptr)/MINBPC(enc)) {
+  case 2:
+    if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) {
+      switch (BYTE_TO_ASCII(enc, ptr)) {
+      case ASCII_l:
+       return ASCII_LT;
+      case ASCII_g:
+       return ASCII_GT;
+      }
+    }
+    break;
+  case 3:
+    if (CHAR_MATCHES(enc, ptr, ASCII_a)) {
+      ptr += MINBPC(enc);
+      if (CHAR_MATCHES(enc, ptr, ASCII_m)) {
+       ptr += MINBPC(enc);
+       if (CHAR_MATCHES(enc, ptr, ASCII_p))
+         return ASCII_AMP;
+      }
+    }
+    break;
+  case 4:
+    switch (BYTE_TO_ASCII(enc, ptr)) {
+    case ASCII_q:
+      ptr += MINBPC(enc);
+      if (CHAR_MATCHES(enc, ptr, ASCII_u)) {
+       ptr += MINBPC(enc);
+       if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+         ptr += MINBPC(enc);
+         if (CHAR_MATCHES(enc, ptr, ASCII_t))
+           return ASCII_QUOT;
+       }
+      }
+      break;
+    case ASCII_a:
+      ptr += MINBPC(enc);
+      if (CHAR_MATCHES(enc, ptr, ASCII_p)) {
+       ptr += MINBPC(enc);
+       if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+         ptr += MINBPC(enc);
+         if (CHAR_MATCHES(enc, ptr, ASCII_s))
+           return ASCII_APOS;
+       }
+      }
+      break;
+    }
+  }
+  return 0;
+}
+
+static
+int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+  for (;;) {
+    switch (BYTE_TYPE(enc, ptr1)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: \
+      if (*ptr1++ != *ptr2++) \
+       return 0;
+    LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
+#undef LEAD_CASE
+      /* fall through */
+      if (*ptr1++ != *ptr2++)
+       return 0;
+      break;
+    case BT_NONASCII:
+    case BT_NMSTRT:
+#ifdef XML_NS
+    case BT_COLON:
+#endif
+    case BT_HEX:
+    case BT_DIGIT:
+    case BT_NAME:
+    case BT_MINUS:
+      if (*ptr2++ != *ptr1++)
+       return 0;
+      if (MINBPC(enc) > 1) {
+       if (*ptr2++ != *ptr1++)
+         return 0;
+       if (MINBPC(enc) > 2) {
+         if (*ptr2++ != *ptr1++)
+           return 0;
+          if (MINBPC(enc) > 3) {
+           if (*ptr2++ != *ptr1++)
+             return 0;
+         }
+       }
+      }
+      break;
+    default:
+      if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
+       return 1;
+      switch (BYTE_TYPE(enc, ptr2)) {
+      case BT_LEAD2:
+      case BT_LEAD3:
+      case BT_LEAD4:
+      case BT_NONASCII:
+      case BT_NMSTRT:
+#ifdef XML_NS
+      case BT_COLON:
+#endif
+      case BT_HEX:
+      case BT_DIGIT:
+      case BT_NAME:
+      case BT_MINUS:
+       return 0;
+      default:
+       return 1;
+      }
+    }
+  }
+  /* not reached */
+}
+
+static
+int PREFIX(nameMatchesAscii)(const ENCODING * enc ATTR_UNUSED, 
+                             const char *     ptr1,
+                             const char *     end1, 
+                             const char *     ptr2)
+{
+  for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
+    if (ptr1 == end1)
+      return 0;
+    if (!CHAR_MATCHES(enc, ptr1, *ptr2))
+      return 0;
+  }
+  return ptr1 == end1;
+}
+
+static
+int PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
+{
+  const char *start = ptr;
+  for (;;) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: ptr += n; break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_NONASCII:
+    case BT_NMSTRT:
+#ifdef XML_NS
+    case BT_COLON:
+#endif
+    case BT_HEX:
+    case BT_DIGIT:
+    case BT_NAME:
+    case BT_MINUS:
+      ptr += MINBPC(enc);
+      break;
+    default:
+      return ptr - start;
+    }
+  }
+}
+
+static
+const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr)
+{
+  for (;;) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_LF:
+    case BT_CR:
+    case BT_S:
+      ptr += MINBPC(enc);
+      break;
+    default:
+      return ptr;
+    }
+  }
+}
+
+static
+void PREFIX(updatePosition)(const ENCODING *enc,
+                           const char *ptr,
+                           const char *end,
+                           POSITION *pos)
+{
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: \
+      ptr += n; \
+      break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_LF:
+      pos->columnNumber = (unsigned)-1;
+      pos->lineNumber++;
+      ptr += MINBPC(enc);
+      break;
+    case BT_CR:
+      pos->lineNumber++;
+      ptr += MINBPC(enc);
+      if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
+       ptr += MINBPC(enc);
+      pos->columnNumber = (unsigned)-1;
+      break;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+    pos->columnNumber++;
+  }
+}
+
+#undef DO_LEAD_CASE
+#undef MULTIBYTE_CASES
+#undef INVALID_CASES
+#undef CHECK_NAME_CASE
+#undef CHECK_NAME_CASES
+#undef CHECK_NMSTRT_CASE
+#undef CHECK_NMSTRT_CASES
diff --git a/lib/expat/xmltok/xmltok_impl.h b/lib/expat/xmltok/xmltok_impl.h
new file mode 100644 (file)
index 0000000..eb92802
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+enum {
+  BT_NONXML,
+  BT_MALFORM,
+  BT_LT,
+  BT_AMP,
+  BT_RSQB,
+  BT_LEAD2,
+  BT_LEAD3,
+  BT_LEAD4,
+  BT_TRAIL,
+  BT_CR,
+  BT_LF,
+  BT_GT,
+  BT_QUOT,
+  BT_APOS,
+  BT_EQUALS,
+  BT_QUEST,
+  BT_EXCL,
+  BT_SOL,
+  BT_SEMI,
+  BT_NUM,
+  BT_LSQB,
+  BT_S,
+  BT_NMSTRT,
+  BT_COLON,
+  BT_HEX,
+  BT_DIGIT,
+  BT_NAME,
+  BT_MINUS,
+  BT_OTHER, /* known not to be a name or name start character */
+  BT_NONASCII, /* might be a name or name start character */
+  BT_PERCNT,
+  BT_LPAR,
+  BT_RPAR,
+  BT_AST,
+  BT_PLUS,
+  BT_COMMA,
+  BT_VERBAR
+};
+
+#include <stddef.h>
diff --git a/lib/expat/xmltok/xmltok_ns.c b/lib/expat/xmltok/xmltok_ns.c
new file mode 100644 (file)
index 0000000..205cfc2
--- /dev/null
@@ -0,0 +1,96 @@
+const ENCODING *NS(xmlrpc_XmlGetUtf8InternalEncoding)(void)
+{
+  return &ns(internal_utf8_encoding).enc;
+}
+
+const ENCODING *NS(xmlrpc_XmlGetUtf16InternalEncoding)(void)
+{
+#if XML_BYTE_ORDER == 12
+  return &ns(internal_little2_encoding).enc;
+#elif XML_BYTE_ORDER == 21
+  return &ns(internal_big2_encoding).enc;
+#else
+  const short n = 1;
+  return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc;
+#endif
+}
+
+static
+const ENCODING *NS(encodings)[] = {
+  &ns(latin1_encoding).enc,
+  &ns(ascii_encoding).enc,
+  &ns(utf8_encoding).enc,
+  &ns(big2_encoding).enc,
+  &ns(big2_encoding).enc,
+  &ns(little2_encoding).enc,
+  &ns(utf8_encoding).enc /* NO_ENC */
+};
+
+static
+int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
+                      const char **nextTokPtr)
+{
+  return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
+}
+
+static
+int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
+                      const char **nextTokPtr)
+{
+  return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
+}
+
+int NS(xmlrpc_XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
+{
+  int i = getEncodingIndex(name);
+  if (i == UNKNOWN_ENC)
+    return 0;
+  SET_INIT_ENC_INDEX(p, i);
+  p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
+  p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
+  p->initEnc.updatePosition = initUpdatePosition;
+  p->encPtr = encPtr;
+  *encPtr = &(p->initEnc);
+  return 1;
+}
+
+static
+const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
+{
+#define ENCODING_MAX 128
+  char buf[ENCODING_MAX];
+  char *p = buf;
+  int i;
+  XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
+  if (ptr != end)
+    return 0;
+  *p = 0;
+  if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2)
+    return enc;
+  i = getEncodingIndex(buf);
+  if (i == UNKNOWN_ENC)
+    return 0;
+  return NS(encodings)[i];
+}
+
+int NS(xmlrpc_XmlParseXmlDecl)(int isGeneralTextEntity,
+                       const ENCODING *enc,
+                       const char *ptr,
+                       const char *end,
+                       const char **badPtr,
+                       const char **versionPtr,
+                       const char **encodingName,
+                       const ENCODING **encoding,
+                       int *standalone)
+{
+  return doParseXmlDecl(NS(findEncoding),
+                       isGeneralTextEntity,
+                       enc,
+                       ptr,
+                       end,
+                       badPtr,
+                       versionPtr,
+                       encodingName,
+                       encoding,
+                       standalone);
+}
diff --git a/lib/expat/xmlwf/.cvsignore b/lib/expat/xmlwf/.cvsignore
new file mode 100644 (file)
index 0000000..f3c7a7c
--- /dev/null
@@ -0,0 +1 @@
+Makefile
diff --git a/lib/expat/xmlwf/Makefile.in b/lib/expat/xmlwf/Makefile.in
new file mode 100644 (file)
index 0000000..0860147
--- /dev/null
@@ -0,0 +1,209 @@
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+ABYSS_SUBDIR = @ABYSS_SUBDIR@
+AS = @AS@
+ASYNCH_CLIENT = @ASYNCH_CLIENT@
+AUTH_CLIENT = @AUTH_CLIENT@
+AVAILABLE_MODULES = @AVAILABLE_MODULES@
+CC = @CC@
+CC_WARN_FLAGS = @CC_WARN_FLAGS@
+CLIENTTEST = @CLIENTTEST@
+CONFIGURE_DATE = @CONFIGURE_DATE@
+CPPTEST = @CPPTEST@
+CPP_WARN_FLAGS = @CPP_WARN_FLAGS@
+CXX = @CXX@
+DLLTOOL = @DLLTOOL@
+EFRPCTEST = @EFRPCTEST@
+EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@
+INTEROP_CGI = @INTEROP_CGI@
+INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@
+LIBTOOL = @LIBTOOL@
+LIBWWW_CFLAGS = @LIBWWW_CFLAGS@
+LIBWWW_CONFIG = @LIBWWW_CONFIG@
+LIBWWW_LDADD = @LIBWWW_LDADD@
+LIBWWW_LIBDIR = @LIBWWW_LIBDIR@
+LIBWWW_RPATH = @LIBWWW_RPATH@
+LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@
+LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@
+LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@
+LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@
+LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+MEERKAT_APP_LIST = @MEERKAT_APP_LIST@
+OBJDUMP = @OBJDUMP@
+PACKAGE = @PACKAGE@
+QUERY_MEERKAT = @QUERY_MEERKAT@
+RANLIB = @RANLIB@
+SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@
+SERVER = @SERVER@
+SERVERTEST = @SERVERTEST@
+SYNCH_CLIENT = @SYNCH_CLIENT@
+VALIDATEE = @VALIDATEE@
+VERSION = @VERSION@
+VERSION_INFO = @VERSION_INFO@
+XMLRPCCPP_H = @XMLRPCCPP_H@
+XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@
+XMLRPC_CGI_H = @XMLRPC_CGI_H@
+XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@
+XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@
+
+EXTRA_DIST = codepage.c filemap.h unixfilemap.c xmlfile.c xmltchar.h              xmlwf.dsp codepage.h readfilemap.c win32filemap.c xmlfile.h              xmlwf.c
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../../xmlrpc_config.h
+CONFIG_CLEAN_FILES = 
+DIST_COMMON = Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib/expat/xmlwf
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$d/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: tags distdir info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/expat/xmlwf/codepage.c b/lib/expat/xmlwf/codepage.c
new file mode 100644 (file)
index 0000000..fe7ab15
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#include "codepage.h"
+
+#ifdef WIN32
+#define STRICT 1
+#define WIN32_LEAN_AND_MEAN 1
+
+#include <windows.h>
+
+int codepageMap(int cp, int *map)
+{
+  int i;
+  CPINFO info;
+  if (!GetCPInfo(cp, &info) || info.MaxCharSize > 2)
+    return 0;
+  for (i = 0; i < 256; i++)
+    map[i] = -1;
+  if (info.MaxCharSize > 1) {
+    for (i = 0; i < MAX_LEADBYTES; i++) {
+      int j, lim;
+      if (info.LeadByte[i] == 0 && info.LeadByte[i + 1] == 0)
+        break;
+      lim = info.LeadByte[i + 1];
+      for (j = info.LeadByte[i]; j < lim; j++)
+       map[j] = -2;
+    }
+  }
+  for (i = 0; i < 256; i++) {
+   if (map[i] == -1) {
+     char c = i;
+     unsigned short n;
+     if (MultiByteToWideChar(cp, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                            &c, 1, &n, 1) == 1)
+       map[i] = n;
+   }
+  }
+  return 1;
+}
+
+int codepageConvert(int cp, const char *p)
+{
+  unsigned short c;
+  if (MultiByteToWideChar(cp, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                         p, 2, &c, 1) == 1)
+    return c;
+  return -1;
+}
+
+#else /* not WIN32 */
+
+int codepageMap(int cp, int *map)
+{
+  return 0;
+}
+
+int codepageConvert(int cp, const char *p)
+{
+  return -1;
+}
+
+#endif /* not WIN32 */
diff --git a/lib/expat/xmlwf/codepage.h b/lib/expat/xmlwf/codepage.h
new file mode 100644 (file)
index 0000000..b19a7f6
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+int codepageMap(int cp, int *map);
+int codepageConvert(int cp, const char *p);
diff --git a/lib/expat/xmlwf/filemap.h b/lib/expat/xmlwf/filemap.h
new file mode 100644 (file)
index 0000000..a0a1847
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+
+#include <stddef.h>
+
+#ifdef XML_UNICODE
+int filemap(const wchar_t *name,
+           void (*processor)(const void *, size_t, const wchar_t *, void *arg),
+           void *arg);
+#else
+int filemap(const char *name,
+           void (*processor)(const void *, size_t, const char *, void *arg),
+           void *arg);
+#endif
diff --git a/lib/expat/xmlwf/readfilemap.c b/lib/expat/xmlwf/readfilemap.c
new file mode 100644 (file)
index 0000000..249af3e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef S_ISREG
+#ifndef S_IFREG
+#define S_IFREG _S_IFREG
+#endif
+#ifndef S_IFMT
+#define S_IFMT _S_IFMT
+#endif
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif /* not S_ISREG */
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0
+#endif
+#endif
+
+int filemap(const char *name,
+           void (*processor)(const void *, size_t, const char *, void *arg),
+           void *arg)
+{
+  size_t nbytes;
+  int fd;
+  int n;
+  struct stat sb;
+  void *p;
+
+  fd = open(name, O_RDONLY|O_BINARY);
+  if (fd < 0) {
+    perror(name);
+    return 0;
+  }
+  if (fstat(fd, &sb) < 0) {
+    perror(name);
+    return 0;
+  }
+  if (!S_ISREG(sb.st_mode)) {
+    fprintf(stderr, "%s: not a regular file\n", name);
+    return 0;
+  }
+  nbytes = sb.st_size;
+  p = malloc(nbytes);
+  if (!p) {
+    fprintf(stderr, "%s: out of memory\n", name);
+    return 0;
+  }
+  n = read(fd, p, nbytes);
+  if (n < 0) {
+    perror(name);
+    close(fd);
+    return 0;
+  }
+  if (n != nbytes) {
+    fprintf(stderr, "%s: read unexpected number of bytes\n", name);
+    close(fd);
+    return 0;
+  }
+  processor(p, nbytes, name, arg);
+  free(p);
+  close(fd);
+  return 1;
+}
diff --git a/lib/expat/xmlwf/unixfilemap.c b/lib/expat/xmlwf/unixfilemap.c
new file mode 100644 (file)
index 0000000..4944b02
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+#include "filemap.h"
+
+int filemap(const char *name,
+           void (*processor)(const void *, size_t, const char *, void *arg),
+           void *arg)
+{
+  int fd;
+  size_t nbytes;
+  struct stat sb;
+  void *p;
+
+  fd = open(name, O_RDONLY);
+  if (fd < 0) {
+    perror(name);
+    return 0;
+  }
+  if (fstat(fd, &sb) < 0) {
+    perror(name);
+    close(fd);
+    return 0;
+  }
+  if (!S_ISREG(sb.st_mode)) {
+    close(fd);
+    fprintf(stderr, "%s: not a regular file\n", name);
+    return 0;
+  }
+  
+  nbytes = sb.st_size;
+  p = (void *)mmap((caddr_t)0, (size_t)nbytes, PROT_READ,
+                  MAP_FILE|MAP_PRIVATE, fd, (off_t)0);
+  if (p == (void *)-1) {
+    perror(name);
+    close(fd);
+    return 0;
+  }
+  processor(p, nbytes, name, arg);
+  munmap((caddr_t)p, nbytes);
+  close(fd);
+  return 1;
+}
diff --git a/lib/expat/xmlwf/win32filemap.c b/lib/expat/xmlwf/win32filemap.c
new file mode 100644 (file)
index 0000000..ec30ff6
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#define STRICT 1
+#define WIN32_LEAN_AND_MEAN 1
+
+#ifdef XML_UNICODE_WCHAR_T
+#ifndef XML_UNICODE
+#define XML_UNICODE
+#endif
+#endif
+
+#ifdef XML_UNICODE
+#define UNICODE
+#define _UNICODE
+#endif /* XML_UNICODE */
+#include <windows.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "filemap.h"
+
+static void win32perror(const TCHAR *);
+
+int filemap(const TCHAR *name,
+           void (*processor)(const void *, size_t, const TCHAR *, void *arg),
+           void *arg)
+{
+  HANDLE f;
+  HANDLE m;
+  DWORD size;
+  DWORD sizeHi;
+  void *p;
+
+  f = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+                         FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+  if (f == INVALID_HANDLE_VALUE) {
+    win32perror(name);
+    return 0;
+  }
+  size = GetFileSize(f, &sizeHi);
+  if (size == (DWORD)-1) {
+    win32perror(name);
+    return 0;
+  }
+  if (sizeHi) {
+    _ftprintf(stderr, _T("%s: bigger than 2Gb\n"), name);
+    return 0;
+  }
+  /* CreateFileMapping barfs on zero length files */
+  if (size == 0) {
+    static const char c = '\0';
+    processor(&c, 0, name, arg);
+    CloseHandle(f);
+    return 1;
+  }
+  m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
+  if (m == NULL) {
+    win32perror(name);
+    CloseHandle(f);
+    return 0;
+  }
+  p = MapViewOfFile(m, FILE_MAP_READ, 0, 0, 0);
+  if (p == NULL) {
+    win32perror(name);
+    CloseHandle(m);
+    CloseHandle(f);
+    return 0;
+  }
+  processor(p, size, name, arg); 
+  UnmapViewOfFile(p);
+  CloseHandle(m);
+  CloseHandle(f);
+  return 1;
+}
+
+static
+void win32perror(const TCHAR *s)
+{
+  LPVOID buf;
+  if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                   NULL,
+                   GetLastError(),
+                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                   (LPTSTR) &buf,
+                   0,
+                   NULL)) {
+    _ftprintf(stderr, _T("%s: %s"), s, buf);
+    fflush(stderr);
+    LocalFree(buf);
+  }
+  else
+    _ftprintf(stderr, _T("%s: unknown Windows error\n"), s);
+}
diff --git a/lib/expat/xmlwf/xmlfile.c b/lib/expat/xmlwf/xmlfile.c
new file mode 100644 (file)
index 0000000..6f79107
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include "xmlparse.h"
+#include "xmlfile.h"
+#include "xmltchar.h"
+#include "filemap.h"
+
+#ifdef _MSC_VER
+#include <io.h>
+#endif
+
+#ifdef _POSIX_SOURCE
+#include <unistd.h>
+#endif
+
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0
+#endif
+#endif
+
+#ifdef _DEBUG
+#define READ_SIZE 16
+#else
+#define READ_SIZE (1024*8)
+#endif
+
+
+
+typedef struct {
+  XML_Parser parser;
+  int *retPtr;
+} PROCESS_ARGS;
+
+static
+void reportError(XML_Parser parser, const XML_Char *filename)
+{
+  int code = XML_GetErrorCode(parser);
+  const XML_Char *message = XML_ErrorString(code);
+  if (message)
+    ftprintf(stdout, T("%s:%d:%d: %s\n"),
+            filename,
+            XML_GetErrorLineNumber(parser),
+            XML_GetErrorColumnNumber(parser),
+            message);
+  else
+    ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code);
+}
+
+static
+void processFile(const void *data,
+                size_t size,
+                const XML_Char *filename,
+                void *args)
+{
+  XML_Parser parser = ((PROCESS_ARGS *)args)->parser;
+  int *retPtr = ((PROCESS_ARGS *)args)->retPtr;
+  if (!XML_Parse(parser, data, size, 1)) {
+    reportError(parser, filename);
+    *retPtr = 0;
+  }
+  else
+    *retPtr = 1;
+}
+
+#ifdef WIN32
+
+static
+int isAsciiLetter(XML_Char c)
+{
+  return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z'));
+}
+
+#endif /* WIN32 */
+
+static
+const XML_Char *resolveSystemId(const XML_Char *base, const XML_Char *systemId, XML_Char **toFree)
+{
+  XML_Char *s;
+  *toFree = 0;
+  if (!base
+      || *systemId == T('/')
+#ifdef WIN32
+      || *systemId == T('\\')
+      || (isAsciiLetter(systemId[0]) && systemId[1] == T(':'))
+#endif
+     )
+    return systemId;
+  *toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2)*sizeof(XML_Char));
+  if (!*toFree)
+    return systemId;
+  tcscpy(*toFree, base);
+  s = *toFree;
+  if (tcsrchr(s, T('/')))
+    s = tcsrchr(s, T('/')) + 1;
+#ifdef WIN32
+  if (tcsrchr(s, T('\\')))
+    s = tcsrchr(s, T('\\')) + 1;
+#endif
+  tcscpy(s, systemId);
+  return *toFree;
+}
+
+static
+int externalEntityRefFilemap(XML_Parser parser,
+                            const XML_Char *context,
+                            const XML_Char *base,
+                            const XML_Char *systemId,
+                            const XML_Char *publicId)
+{
+  int result;
+  XML_Char *s;
+  const XML_Char *filename;
+  XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
+  PROCESS_ARGS args;
+  args.retPtr = &result;
+  args.parser = entParser;
+  filename = resolveSystemId(base, systemId, &s);
+  XML_SetBase(entParser, filename);
+  if (!filemap(filename, processFile, &args))
+    result = 0;
+  free(s);
+  XML_ParserFree(entParser);
+  return result;
+}
+
+static
+int processStream(const XML_Char *filename, XML_Parser parser)
+{
+  int fd = topen(filename, O_BINARY|O_RDONLY);
+  if (fd < 0) {
+    tperror(filename);
+    return 0;
+  }
+  for (;;) {
+    int nread;
+    char *buf = XML_GetBuffer(parser, READ_SIZE);
+    if (!buf) {
+      close(fd);
+      ftprintf(stderr, T("%s: out of memory\n"), filename);
+      return 0;
+    }
+    nread = read(fd, buf, READ_SIZE);
+    if (nread < 0) {
+      tperror(filename);
+      close(fd);
+      return 0;
+    }
+    if (!XML_ParseBuffer(parser, nread, nread == 0)) {
+      reportError(parser, filename);
+      close(fd);
+      return 0;
+    }
+    if (nread == 0) {
+      close(fd);
+      break;;
+    }
+  }
+  return 1;
+}
+
+static
+int externalEntityRefStream(XML_Parser parser,
+                           const XML_Char *context,
+                           const XML_Char *base,
+                           const XML_Char *systemId,
+                           const XML_Char *publicId)
+{
+  XML_Char *s;
+  const XML_Char *filename;
+  int ret;
+  XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
+  filename = resolveSystemId(base, systemId, &s);
+  XML_SetBase(entParser, filename);
+  ret = processStream(filename, entParser);
+  free(s);
+  XML_ParserFree(entParser);
+  return ret;
+}
+
+int XML_ProcessFile(XML_Parser parser,
+                   const XML_Char *filename,
+                   unsigned flags)
+{
+  int result;
+
+  if (!XML_SetBase(parser, filename)) {
+    ftprintf(stderr, T("%s: out of memory"), filename);
+    exit(1);
+  }
+
+  if (flags & XML_EXTERNAL_ENTITIES)
+      XML_SetExternalEntityRefHandler(parser,
+                                     (flags & XML_MAP_FILE)
+                                     ? externalEntityRefFilemap
+                                     : externalEntityRefStream);
+  if (flags & XML_MAP_FILE) {
+    PROCESS_ARGS args;
+    args.retPtr = &result;
+    args.parser = parser;
+    if (!filemap(filename, processFile, &args))
+      result = 0;
+  }
+  else
+    result = processStream(filename, parser);
+  return result;
+}
diff --git a/lib/expat/xmlwf/xmlfile.h b/lib/expat/xmlwf/xmlfile.h
new file mode 100644 (file)
index 0000000..0c7ac19
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#define XML_MAP_FILE 01
+#define XML_EXTERNAL_ENTITIES 02
+
+extern int XML_ProcessFile(XML_Parser parser,
+                          const XML_Char *filename,
+                          unsigned flags);
diff --git a/lib/expat/xmlwf/xmltchar.h b/lib/expat/xmlwf/xmltchar.h
new file mode 100644 (file)
index 0000000..1088575
--- /dev/null
@@ -0,0 +1,36 @@
+#ifdef XML_UNICODE
+#ifndef XML_UNICODE_WCHAR_T
+#error xmlwf requires a 16-bit Unicode-compatible wchar_t 
+#endif
+#define T(x) L ## x
+#define ftprintf fwprintf
+#define tfopen _wfopen
+#define fputts fputws
+#define puttc putwc
+#define tcscmp wcscmp
+#define tcscpy wcscpy
+#define tcscat wcscat
+#define tcschr wcschr
+#define tcsrchr wcsrchr
+#define tcslen wcslen
+#define tperror _wperror
+#define topen _wopen
+#define tmain wmain
+#define tremove _wremove
+#else /* not XML_UNICODE */
+#define T(x) x
+#define ftprintf fprintf
+#define tfopen fopen
+#define fputts fputs
+#define puttc putc
+#define tcscmp strcmp
+#define tcscpy strcpy
+#define tcscat strcat
+#define tcschr strchr
+#define tcsrchr strrchr
+#define tcslen strlen
+#define tperror perror
+#define topen open
+#define tmain main
+#define tremove remove
+#endif /* not XML_UNICODE */
diff --git a/lib/expat/xmlwf/xmlwf.c b/lib/expat/xmlwf/xmlwf.c
new file mode 100644 (file)
index 0000000..2b8fe12
--- /dev/null
@@ -0,0 +1,766 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file copying.txt for copying permission.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "xmlparse.h"
+#include "codepage.h"
+#include "xmlfile.h"
+#include "xmltchar.h"
+
+#ifdef _MSC_VER
+#include <crtdbg.h>
+#endif
+
+/* This ensures proper sorting. */
+
+#define NSSEP T('\001')
+
+static void characterData(void *userData, const XML_Char *s, int len)
+{
+  FILE *fp = userData;
+  for (; len > 0; --len, ++s) {
+    switch (*s) {
+    case T('&'):
+      fputts(T("&amp;"), fp);
+      break;
+    case T('<'):
+      fputts(T("&lt;"), fp);
+      break;
+    case T('>'):
+      fputts(T("&gt;"), fp);
+      break;
+#ifdef W3C14N
+    case 13:
+      fputts(T("&#xD;"), fp);
+      break;
+#else
+    case T('"'):
+      fputts(T("&quot;"), fp);
+      break;
+    case 9:
+    case 10:
+    case 13:
+      ftprintf(fp, T("&#%d;"), *s);
+      break;
+#endif
+    default:
+      puttc(*s, fp);
+      break;
+    }
+  }
+}
+
+static void attributeValue(FILE *fp, const XML_Char *s)
+{
+  puttc(T('='), fp);
+  puttc(T('"'), fp);
+  for (;;) {
+    switch (*s) {
+    case 0:
+    case NSSEP:
+      puttc(T('"'), fp);
+      return;
+    case T('&'):
+      fputts(T("&amp;"), fp);
+      break;
+    case T('<'):
+      fputts(T("&lt;"), fp);
+      break;
+    case T('"'):
+      fputts(T("&quot;"), fp);
+      break;
+#ifdef W3C14N
+    case 9:
+      fputts(T("&#x9;"), fp);
+      break;
+    case 10:
+      fputts(T("&#xA;"), fp);
+      break;
+    case 13:
+      fputts(T("&#xD;"), fp);
+      break;
+#else
+    case T('>'):
+      fputts(T("&gt;"), fp);
+      break;
+    case 9:
+    case 10:
+    case 13:
+      ftprintf(fp, T("&#%d;"), *s);
+      break;
+#endif
+    default:
+      puttc(*s, fp);
+      break;
+    }
+    s++;
+  }
+}
+
+/* Lexicographically comparing UTF-8 encoded attribute values,
+is equivalent to lexicographically comparing based on the character number. */
+
+static int attcmp(const void *att1, const void *att2)
+{
+  return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
+}
+
+static void startElement(void *userData, const XML_Char *name, const XML_Char **atts)
+{
+  int nAtts;
+  const XML_Char **p;
+  FILE *fp = userData;
+  puttc(T('<'), fp);
+  fputts(name, fp);
+
+  p = atts;
+  while (*p)
+    ++p;
+  nAtts = (p - atts) >> 1;
+  if (nAtts > 1)
+    qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
+  while (*atts) {
+    puttc(T(' '), fp);
+    fputts(*atts++, fp);
+    attributeValue(fp, *atts);
+    atts++;
+  }
+  puttc(T('>'), fp);
+}
+
+static void endElement(void *userData, const XML_Char *name)
+{
+  FILE *fp = userData;
+  puttc(T('<'), fp);
+  puttc(T('/'), fp);
+  fputts(name, fp);
+  puttc(T('>'), fp);
+}
+
+static int nsattcmp(const void *p1, const void *p2)
+{
+  const XML_Char *att1 = *(const XML_Char **)p1;
+  const XML_Char *att2 = *(const XML_Char **)p2;
+  int sep1 = (tcsrchr(att1, NSSEP) != 0);
+  int sep2 = (tcsrchr(att1, NSSEP) != 0);
+  if (sep1 != sep2)
+    return sep1 - sep2;
+  return tcscmp(att1, att2);
+}
+
+static void startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
+{
+  int nAtts;
+  int nsi;
+  const XML_Char **p;
+  FILE *fp = userData;
+  const XML_Char *sep;
+  puttc(T('<'), fp);
+
+  sep = tcsrchr(name, NSSEP);
+  if (sep) {
+    fputts(T("n1:"), fp);
+    fputts(sep + 1, fp);
+    fputts(T(" xmlns:n1"), fp);
+    attributeValue(fp, name);
+    nsi = 2;
+  }
+  else {
+    fputts(name, fp);
+    nsi = 1;
+  }
+
+  p = atts;
+  while (*p)
+    ++p;
+  nAtts = (p - atts) >> 1;
+  if (nAtts > 1)
+    qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
+  while (*atts) {
+    name = *atts++;
+    sep = tcsrchr(name, NSSEP);
+    puttc(T(' '), fp);
+    if (sep) {
+      ftprintf(fp, T("n%d:"), nsi);
+      fputts(sep + 1, fp);
+    }
+    else
+      fputts(name, fp);
+    attributeValue(fp, *atts);
+    if (sep) {
+      ftprintf(fp, T(" xmlns:n%d"), nsi++);
+      attributeValue(fp, name);
+    }
+    atts++;
+  }
+  puttc(T('>'), fp);
+}
+
+static void endElementNS(void *userData, const XML_Char *name)
+{
+  FILE *fp = userData;
+  const XML_Char *sep;
+  puttc(T('<'), fp);
+  puttc(T('/'), fp);
+  sep = tcsrchr(name, NSSEP);
+  if (sep) {
+    fputts(T("n1:"), fp);
+    fputts(sep + 1, fp);
+  }
+  else
+    fputts(name, fp);
+  puttc(T('>'), fp);
+}
+
+#ifndef W3C14N
+
+static void processingInstruction(void *userData, const XML_Char *target, const XML_Char *data)
+{
+  FILE *fp = userData;
+  puttc(T('<'), fp);
+  puttc(T('?'), fp);
+  fputts(target, fp);
+  puttc(T(' '), fp);
+  fputts(data, fp);
+  puttc(T('?'), fp);
+  puttc(T('>'), fp);
+}
+
+#endif /* not W3C14N */
+
+static void defaultCharacterData(XML_Parser parser, const XML_Char *s, int len)
+{
+  XML_DefaultCurrent(parser);
+}
+
+static void defaultStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts)
+{
+  XML_DefaultCurrent(parser);
+}
+
+static void defaultEndElement(XML_Parser parser, const XML_Char *name)
+{
+  XML_DefaultCurrent(parser);
+}
+
+static void defaultProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data)
+{
+  XML_DefaultCurrent(parser);
+}
+
+static void nopCharacterData(XML_Parser parser, const XML_Char *s, int len)
+{
+}
+
+static void nopStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts)
+{
+}
+
+static void nopEndElement(XML_Parser parser, const XML_Char *name)
+{
+}
+
+static void nopProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data)
+{
+}
+
+static void markup(XML_Parser parser, const XML_Char *s, int len)
+{
+  FILE *fp = XML_GetUserData(parser);
+  for (; len > 0; --len, ++s)
+    puttc(*s, fp);
+}
+
+static
+void metaLocation(XML_Parser parser)
+{
+  const XML_Char *uri = XML_GetBase(parser);
+  if (uri)
+    ftprintf(XML_GetUserData(parser), T(" uri=\"%s\""), uri);
+  ftprintf(XML_GetUserData(parser),
+           T(" byte=\"%ld\" nbytes=\"%d\" line=\"%d\" col=\"%d\""),
+          XML_GetCurrentByteIndex(parser),
+          XML_GetCurrentByteCount(parser),
+          XML_GetCurrentLineNumber(parser),
+          XML_GetCurrentColumnNumber(parser));
+}
+
+static
+void metaStartDocument(XML_Parser parser)
+{
+  fputts(T("<document>\n"), XML_GetUserData(parser));
+}
+
+static
+void metaEndDocument(XML_Parser parser)
+{
+  fputts(T("</document>\n"), XML_GetUserData(parser));
+}
+
+static
+void metaStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts)
+{
+  FILE *fp = XML_GetUserData(parser);
+  const XML_Char **specifiedAttsEnd
+    = atts + XML_GetSpecifiedAttributeCount(parser);
+  const XML_Char **idAttPtr;
+  int idAttIndex = XML_GetIdAttributeIndex(parser);
+  if (idAttIndex < 0)
+    idAttPtr = 0;
+  else
+    idAttPtr = atts + idAttIndex;
+    
+  ftprintf(fp, T("<starttag name=\"%s\""), name);
+  metaLocation(parser);
+  if (*atts) {
+    fputts(T(">\n"), fp);
+    do {
+      ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
+      characterData(fp, atts[1], tcslen(atts[1]));
+      if (atts >= specifiedAttsEnd)
+       fputts(T("\" defaulted=\"yes\"/>\n"), fp);
+      else if (atts == idAttPtr)
+       fputts(T("\" id=\"yes\"/>\n"), fp);
+      else
+       fputts(T("\"/>\n"), fp);
+    } while (*(atts += 2));
+    fputts(T("</starttag>\n"), fp);
+  }
+  else
+    fputts(T("/>\n"), fp);
+}
+
+static
+void metaEndElement(XML_Parser parser, const XML_Char *name)
+{
+  FILE *fp = XML_GetUserData(parser);
+  ftprintf(fp, T("<endtag name=\"%s\""), name);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data)
+{
+  FILE *fp = XML_GetUserData(parser);
+  ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
+  characterData(fp, data, tcslen(data));
+  puttc(T('"'), fp);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaComment(XML_Parser parser, const XML_Char *data)
+{
+  FILE *fp = XML_GetUserData(parser);
+  fputts(T("<comment data=\""), fp);
+  characterData(fp, data, tcslen(data));
+  puttc(T('"'), fp);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaStartCdataSection(XML_Parser parser)
+{
+  FILE *fp = XML_GetUserData(parser);
+  fputts(T("<startcdata"), fp);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaEndCdataSection(XML_Parser parser)
+{
+  FILE *fp = XML_GetUserData(parser);
+  fputts(T("<endcdata"), fp);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaCharacterData(XML_Parser parser, const XML_Char *s, int len)
+{
+  FILE *fp = XML_GetUserData(parser);
+  fputts(T("<chars str=\""), fp);
+  characterData(fp, s, len);
+  puttc(T('"'), fp);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaStartDoctypeDecl(XML_Parser parser, const XML_Char *doctypeName)
+{
+  FILE *fp = XML_GetUserData(parser);
+  ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaEndDoctypeDecl(XML_Parser parser)
+{
+  FILE *fp = XML_GetUserData(parser);
+  fputts(T("<enddoctype"), fp);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaUnparsedEntityDecl(XML_Parser parser,
+                           const XML_Char *entityName,
+                           const XML_Char *base,
+                           const XML_Char *systemId,
+                           const XML_Char *publicId,
+                           const XML_Char *notationName)
+{
+  FILE *fp = XML_GetUserData(parser);
+  ftprintf(fp, T("<entity name=\"%s\""), entityName);
+  if (publicId)
+    ftprintf(fp, T(" public=\"%s\""), publicId);
+  fputts(T(" system=\""), fp);
+  characterData(fp, systemId, tcslen(systemId));
+  puttc(T('"'), fp);
+  ftprintf(fp, T(" notation=\"%s\""), notationName);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaNotationDecl(XML_Parser parser,
+                     const XML_Char *notationName,
+                     const XML_Char *base,
+                     const XML_Char *systemId,
+                     const XML_Char *publicId)
+{
+  FILE *fp = XML_GetUserData(parser);
+  ftprintf(fp, T("<notation name=\"%s\""), notationName);
+  if (publicId)
+    ftprintf(fp, T(" public=\"%s\""), publicId);
+  if (systemId) {
+    fputts(T(" system=\""), fp);
+    characterData(fp, systemId, tcslen(systemId));
+    puttc(T('"'), fp);
+  }
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+
+static
+void metaExternalParsedEntityDecl(XML_Parser parser,
+                                 const XML_Char *entityName,
+                                 const XML_Char *base,
+                                 const XML_Char *systemId,
+                                 const XML_Char *publicId)
+{
+  FILE *fp = XML_GetUserData(parser);
+  ftprintf(fp, T("<entity name=\"%s\""), entityName);
+  if (publicId)
+    ftprintf(fp, T(" public=\"%s\""), publicId);
+  fputts(T(" system=\""), fp);
+  characterData(fp, systemId, tcslen(systemId));
+  puttc(T('"'), fp);
+  metaLocation(parser);
+  fputts(T("/>\n"), fp);
+}
+
+static
+void metaInternalParsedEntityDecl(XML_Parser parser,
+                                 const XML_Char *entityName,
+                                 const XML_Char *text,
+                                 int textLen)
+{
+  FILE *fp = XML_GetUserData(parser);
+  ftprintf(fp, T("<entity name=\"%s\""), entityName);
+  metaLocation(parser);
+  puttc(T('>'), fp);
+  characterData(fp, text, textLen);
+  fputts(T("</entity/>\n"), fp);
+}
+
+static
+void metaStartNamespaceDecl(XML_Parser parser,
+                           const XML_Char *prefix,
+                           const XML_Char *uri)
+{
+  FILE *fp = XML_GetUserData(parser);
+  fputts(T("<startns"), fp);
+  if (prefix)
+    ftprintf(fp, T(" prefix=\"%s\""), prefix);
+  if (uri) {
+    fputts(T(" ns=\""), fp);
+    characterData(fp, uri, tcslen(uri));
+    fputts(T("\"/>\n"), fp);
+  }
+  else
+    fputts(T("/>\n"), fp);
+}
+
+static
+void metaEndNamespaceDecl(XML_Parser parser, const XML_Char *prefix)
+{
+  FILE *fp = XML_GetUserData(parser);
+  if (!prefix)
+    fputts(T("<endns/>\n"), fp);
+  else
+    ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
+}
+
+static
+int unknownEncodingConvert(void *data, const char *p)
+{
+  return codepageConvert(*(int *)data, p);
+}
+
+static
+int unknownEncoding(void *userData,
+                   const XML_Char *name,
+                   XML_Encoding *info)
+{
+  int cp;
+  static const XML_Char prefixL[] = T("windows-");
+  static const XML_Char prefixU[] = T("WINDOWS-");
+  int i;
+
+  for (i = 0; prefixU[i]; i++)
+    if (name[i] != prefixU[i] && name[i] != prefixL[i])
+      return 0;
+  
+  cp = 0;
+  for (; name[i]; i++) {
+    static const XML_Char digits[] = T("0123456789");
+    const XML_Char *s = tcschr(digits, name[i]);
+    if (!s)
+      return 0;
+    cp *= 10;
+    cp += s - digits;
+    if (cp >= 0x10000)
+      return 0;
+  }
+  if (!codepageMap(cp, info->map))
+    return 0;
+  info->convert = unknownEncodingConvert;
+  /* We could just cast the code page integer to a void *,
+  and avoid the use of release. */
+  info->release = free;
+  info->data = malloc(sizeof(int));
+  if (!info->data)
+    return 0;
+  *(int *)info->data = cp;
+  return 1;
+}
+
+static
+int notStandalone(void *userData)
+{
+  return 0;
+}
+
+static
+void usage(const XML_Char *prog)
+{
+  ftprintf(stderr, T("usage: %s [-n] [-p] [-r] [-s] [-w] [-x] [-d output-dir] [-e encoding] file ...\n"), prog);
+  exit(1);
+}
+
+int tmain(int argc, XML_Char **argv)
+{
+  int i, j;
+  const XML_Char *outputDir = 0;
+  const XML_Char *encoding = 0;
+  unsigned processFlags = XML_MAP_FILE;
+  int windowsCodePages = 0;
+  int outputType = 0;
+  int useNamespaces = 0;
+  int requireStandalone = 0;
+  int paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+
+#ifdef _MSC_VER
+  _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
+#endif
+
+  i = 1;
+  j = 0;
+  while (i < argc) {
+    if (j == 0) {
+      if (argv[i][0] != T('-'))
+       break;
+      if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
+       i++;
+       break;
+      }
+      j++;
+    }
+    switch (argv[i][j]) {
+    case T('r'):
+      processFlags &= ~XML_MAP_FILE;
+      j++;
+      break;
+    case T('s'):
+      requireStandalone = 1;
+      j++;
+      break;
+    case T('n'):
+      useNamespaces = 1;
+      j++;
+      break;
+    case T('p'):
+      paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
+      /* fall through */
+    case T('x'):
+      processFlags |= XML_EXTERNAL_ENTITIES;
+      j++;
+      break;
+    case T('w'):
+      windowsCodePages = 1;
+      j++;
+      break;
+    case T('m'):
+      outputType = 'm';
+      j++;
+      break;
+    case T('c'):
+      outputType = 'c';
+      useNamespaces = 0;
+      j++;
+      break;
+    case T('t'):
+      outputType = 't';
+      j++;
+      break;
+    case T('d'):
+      if (argv[i][j + 1] == T('\0')) {
+       if (++i == argc)
+         usage(argv[0]);
+       outputDir = argv[i];
+      }
+      else
+       outputDir = argv[i] + j + 1;
+      i++;
+      j = 0;
+      break;
+    case T('e'):
+      if (argv[i][j + 1] == T('\0')) {
+       if (++i == argc)
+         usage(argv[0]);
+       encoding = argv[i];
+      }
+      else
+       encoding = argv[i] + j + 1;
+      i++;
+      j = 0;
+      break;
+    case T('\0'):
+      if (j > 1) {
+       i++;
+       j = 0;
+       break;
+      }
+      /* fall through */
+    default:
+      usage(argv[0]);
+    }
+  }
+  if (i == argc)
+    usage(argv[0]);
+  for (; i < argc; i++) {
+    FILE *fp = 0;
+    XML_Char *outName = 0;
+    int result;
+    XML_Parser parser;
+    if (useNamespaces)
+      parser = XML_ParserCreateNS(encoding, NSSEP);
+    else
+      parser = XML_ParserCreate(encoding);
+    if (requireStandalone)
+      XML_SetNotStandaloneHandler(parser, notStandalone);
+    XML_SetParamEntityParsing(parser, paramEntityParsing);
+    if (outputType == 't') {
+      /* This is for doing timings; this gives a more realistic estimate of
+        the parsing time. */
+      outputDir = 0;
+      XML_SetElementHandler(parser, nopStartElement, nopEndElement);
+      XML_SetCharacterDataHandler(parser, nopCharacterData);
+      XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
+    }
+    else if (outputDir) {
+      const XML_Char *file = argv[i];
+      if (tcsrchr(file, T('/')))
+       file = tcsrchr(file, T('/')) + 1;
+#ifdef WIN32
+      if (tcsrchr(file, T('\\')))
+       file = tcsrchr(file, T('\\')) + 1;
+#endif
+      outName = malloc((tcslen(outputDir) + tcslen(file) + 2) * sizeof(XML_Char));
+      tcscpy(outName, outputDir);
+      tcscat(outName, T("/"));
+      tcscat(outName, file);
+      fp = tfopen(outName, T("wb"));
+      if (!fp) {
+       tperror(outName);
+       exit(1);
+      }
+      setvbuf(fp, NULL, _IOFBF, 16384);
+#ifdef XML_UNICODE
+      puttc(0xFEFF, fp);
+#endif
+      XML_SetUserData(parser, fp);
+      switch (outputType) {
+      case 'm':
+       XML_UseParserAsHandlerArg(parser);
+       XML_SetElementHandler(parser, metaStartElement, metaEndElement);
+       XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
+       XML_SetCommentHandler(parser, metaComment);
+       XML_SetCdataSectionHandler(parser, metaStartCdataSection, metaEndCdataSection);
+       XML_SetCharacterDataHandler(parser, metaCharacterData);
+       XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl, metaEndDoctypeDecl);
+       XML_SetUnparsedEntityDeclHandler(parser, metaUnparsedEntityDecl);
+       XML_SetNotationDeclHandler(parser, metaNotationDecl);
+       XML_SetExternalParsedEntityDeclHandler(parser, metaExternalParsedEntityDecl);
+       XML_SetInternalParsedEntityDeclHandler(parser, metaInternalParsedEntityDecl);
+       XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl, metaEndNamespaceDecl);
+       metaStartDocument(parser);
+       break;
+      case 'c':
+       XML_UseParserAsHandlerArg(parser);
+       XML_SetDefaultHandler(parser, markup);
+       XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
+       XML_SetCharacterDataHandler(parser, defaultCharacterData);
+       XML_SetProcessingInstructionHandler(parser, defaultProcessingInstruction);
+       break;
+      default:
+       if (useNamespaces)
+         XML_SetElementHandler(parser, startElementNS, endElementNS);
+       else
+         XML_SetElementHandler(parser, startElement, endElement);
+       XML_SetCharacterDataHandler(parser, characterData);
+#ifndef W3C14N
+       XML_SetProcessingInstructionHandler(parser, processingInstruction);
+#endif /* not W3C14N */
+       break;
+      }
+    }
+    if (windowsCodePages)
+      XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
+    result = XML_ProcessFile(parser, argv[i], processFlags);
+    if (outputDir) {
+      if (outputType == 'm')
+       metaEndDocument(parser);
+      fclose(fp);
+      if (!result)
+       tremove(outName);
+      free(outName);
+    }
+    XML_ParserFree(parser);
+  }
+  return 0;
+}
diff --git a/lib/expat/xmlwf/xmlwf.dsp b/lib/expat/xmlwf/xmlwf.dsp
new file mode 100644 (file)
index 0000000..1ca4f42
--- /dev/null
@@ -0,0 +1,136 @@
+# Microsoft Developer Studio Project File - Name="xmlwf" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=xmlwf - Win32 Release\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "xmlwf.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "xmlwf.mak" CFG="xmlwf - Win32 Release"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "xmlwf - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "xmlwf - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "xmlwf - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir ".\Release"\r
+# PROP BASE Intermediate_Dir ".\Release"\r
+# PROP BASE Target_Dir "."\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir ".\Release"\r
+# PROP Intermediate_Dir ".\Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir "."\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c\r
+# ADD CPP /nologo /W3 /GX /O2 /I "..\xmlparse" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllimport) /YX /FD /c\r
+# ADD BASE RSC /l 0x809 /d "NDEBUG"\r
+# ADD RSC /l 0x809 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 setargv.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlwf.exe"\r
+\r
+!ELSEIF  "$(CFG)" == "xmlwf - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir ".\Debug"\r
+# PROP BASE Intermediate_Dir ".\Debug"\r
+# PROP BASE Target_Dir "."\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir ".\Debug"\r
+# PROP Intermediate_Dir ".\Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir "."\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".\xmlparse" /I "..\xmlparse" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllimport) /YX /FD /c\r
+# ADD BASE RSC /l 0x809 /d "_DEBUG"\r
+# ADD RSC /l 0x809 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386\r
+# ADD LINK32 setargv.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\dbgbin\xmlwf.exe"\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "xmlwf - Win32 Release"\r
+# Name "xmlwf - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"\r
+# Begin Source File\r
+\r
+SOURCE=.\codepage.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\readfilemap.c\r
+# PROP Exclude_From_Build 1\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\unixfilemap.c\r
+# PROP Exclude_From_Build 1\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\win32filemap.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\xmlfile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\xmlwf.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"\r
+# Begin Source File\r
+\r
+SOURCE=.\codepage.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\xmlfile.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\xmltchar.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
new file mode 100644 (file)
index 0000000..aff219d
--- /dev/null
@@ -0,0 +1,71 @@
+###############################################################################
+# This directory builds libxmlrpc_util, which contains utility
+# functions that are used by the Xmlprc-c # libraries, and also
+# directly by Xmlrpc-c programs.
+#
+# The functions in this library are characterized by being general purpose
+# programming functions, such as one might wish were in the standard C
+# library, which have nothing in particular to do with XML-RPC.
+###############################################################################
+
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+SUBDIR = lib/libutil
+# BLDDIR is for use in places where a symbolic link won't work.
+# BUILDDIR is for places in Makefile.common that can use the 'blddir'
+# symbolic link (but in other directories, doesn't).
+BLDDIR = ../..
+BUILDDIR = blddir
+VPATH = .:$(SRCDIR)
+
+include $(BLDDIR)/Makefile.config
+
+default: all
+
+all: libxmlrpc_util.la
+
+LIBXMLRPC_UTIL_OBJS = \
+  casprintf.lo \
+  error.lo \
+  make_printable.lo \
+  memblock.lo \
+  resource.lo \
+  sleep.lo \
+
+INCLUDES = -Iblddir -I$(SRCDIR) \
+           -Isrcdir/include -Isrcdir/lib/util/include
+
+LDFLAGS = $(LADD)
+
+LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR) $(LADD)
+
+libxmlrpc_util.la: $(LIBXMLRPC_UTIL_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+$(LIBXMLRPC_UTIL_OBJS):%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+LTLIBRARIES_TO_INSTALL = libxmlrpc_util.la
+
+.PHONY: install
+install: install-common
+
+.PHONY: clean distclean
+clean: clean-common
+
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
+
+# This 'Makefile.common' dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/Makefile.common: srcdir blddir
+
+include $(SRCDIR)/Makefile.common
+
+include Makefile.depend
diff --git a/lib/libutil/Makefile.depend b/lib/libutil/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/libutil/casprintf.c b/lib/libutil/casprintf.c
new file mode 100644 (file)
index 0000000..45a8e0e
--- /dev/null
@@ -0,0 +1,93 @@
+#define _GNU_SOURCE
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "xmlrpc_config.h"  /* For HAVE_ASPRINTF, __inline__ */
+#include "xmlrpc-c/string_int.h"
+
+
+
+static __inline__ void
+simpleVasprintf(char **      const retvalP,
+                const char * const fmt,
+                va_list            varargs) {
+/*----------------------------------------------------------------------------
+   This is a poor man's implementation of vasprintf(), of GNU fame.
+-----------------------------------------------------------------------------*/
+    size_t const initialSize = 4096;
+    char * result;
+
+    result = malloc(initialSize);
+    if (result != NULL) {
+        size_t bytesNeeded;
+        bytesNeeded = vsnprintf(result, initialSize, fmt, varargs);
+        if (bytesNeeded > initialSize) {
+            free(result);
+            result = malloc(bytesNeeded);
+            if (result != NULL)
+                vsnprintf(result, bytesNeeded, fmt, varargs);
+        } else if (bytesNeeded == initialSize) {
+            if (result[initialSize-1] != '\0') {
+                /* This is one of those old systems where vsnprintf()
+                   returns the number of bytes it used, instead of the
+                   number that it needed, and it in fact needed more than
+                   we gave it.  Rather than mess with this highly unlikely
+                   case (old system and string > 4095 characters), we just
+                   treat this like an out of memory failure.
+                */
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    *retvalP = result;
+}
+
+
+
+const char * const xmlrpc_strsol = "[insufficient memory to build string]";
+
+
+
+void
+xmlrpc_vasprintf(const char ** const retvalP,
+                 const char *  const fmt,
+                 va_list             varargs) {
+    
+    char * string;
+
+#if HAVE_ASPRINTF
+    vasprintf(&string, fmt, varargs);
+#else
+    simpleVasprintf(&string, fmt, varargs);
+#endif
+
+    if (string == NULL)
+        *retvalP = xmlrpc_strsol;
+    else
+        *retvalP = string;
+}
+
+
+
+void GNU_PRINTF_ATTR(2,3)
+xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...) {
+
+    va_list varargs;  /* mysterious structure used by variable arg facility */
+
+    va_start(varargs, fmt); /* start up the mysterious variable arg facility */
+
+    xmlrpc_vasprintf(retvalP, fmt, varargs);
+
+    va_end(varargs);
+}
+
+
+
+void
+xmlrpc_strfree(const char * const string) {
+
+    if (string != xmlrpc_strsol)
+        free((void *)string);
+}
diff --git a/lib/libutil/error.c b/lib/libutil/error.c
new file mode 100644 (file)
index 0000000..eec5185
--- /dev/null
@@ -0,0 +1,158 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/util.h"
+
+
+#define ERROR_BUFFER_SZ (256)
+
+void
+xmlrpc_assertion_failed(const char * const fileName,
+                        int          const lineNumber) {
+
+    fprintf(stderr, "%s:%d: assertion failed\n", fileName, lineNumber);
+    abort();
+}
+
+
+
+static const char * const default_fault_string =
+    "Not enough memory for error message";
+
+void xmlrpc_env_init (xmlrpc_env* env)
+{
+    XMLRPC_ASSERT(env != NULL);
+
+    env->fault_occurred = 0;
+    env->fault_code     = 0;
+    env->fault_string   = NULL;
+}
+
+void
+xmlrpc_env_clean(xmlrpc_env * const envP) {
+
+    XMLRPC_ASSERT(envP != NULL);
+    XMLRPC_ASSERT(envP->fault_string != XMLRPC_BAD_POINTER);
+
+    /* env->fault_string may be one of three things:
+    **   1) a NULL pointer
+    **   2) a pointer to the default_fault_string
+    **   3) a pointer to a malloc'd fault string
+    ** If we have case (3), we'll need to free it. */
+    if (envP->fault_string && envP->fault_string != default_fault_string)
+        free(envP->fault_string);
+    envP->fault_string = XMLRPC_BAD_POINTER;
+}
+
+
+
+void 
+xmlrpc_env_set_fault(xmlrpc_env * const envP,
+                     int          const faultCode, 
+                     const char * const faultDescription) {
+
+    XMLRPC_ASSERT(envP != NULL); 
+    XMLRPC_ASSERT(faultDescription != NULL);
+
+    /* Clean up any leftover pointers. */
+    xmlrpc_env_clean(envP);
+
+    envP->fault_occurred = 1;
+    envP->fault_code     = faultCode;
+
+    /* Try to copy the fault string. If this fails, use a default. */
+    envP->fault_string = strdup(faultDescription);
+    if (envP->fault_string == NULL)
+        envP->fault_string = (char *)default_fault_string;
+}
+
+
+
+static void
+set_fault_formatted_v(xmlrpc_env * const envP,
+                      int          const code,
+                      const char * const format,
+                      va_list      const args) {
+
+    char buffer[ERROR_BUFFER_SZ];
+
+    vsnprintf(buffer, ERROR_BUFFER_SZ, format, args);
+
+    /* vsnprintf is guaranteed to terminate the buffer, but we're paranoid. */
+    buffer[ERROR_BUFFER_SZ - 1] = '\0';
+
+    /* Set the fault. */
+    xmlrpc_env_set_fault(envP, code, buffer);
+}
+
+
+
+void 
+xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP, 
+                               int          const code,
+                               const char * const format, 
+                               ...) {
+    va_list args;
+
+    XMLRPC_ASSERT(envP != NULL);
+    XMLRPC_ASSERT(format != NULL);
+
+    /* Print our error message to the buffer. */
+    va_start(args, format);
+    set_fault_formatted_v(envP, code, format, args);
+    va_end(args);
+}
+
+
+
+void
+xmlrpc_faultf(xmlrpc_env * const envP,
+              const char * const format,
+              ...) {
+
+    va_list args;
+
+    XMLRPC_ASSERT(envP != NULL);
+    XMLRPC_ASSERT(format != NULL);
+
+    /* Print our error message to the buffer. */
+    va_start(args, format);
+    set_fault_formatted_v(envP, XMLRPC_INTERNAL_ERROR, format, args);
+    va_end(args);
+
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
diff --git a/lib/libutil/make_printable.c b/lib/libutil/make_printable.c
new file mode 100644 (file)
index 0000000..8caf4da
--- /dev/null
@@ -0,0 +1,100 @@
+#define _GNU_SOURCE
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/string_int.h"
+
+
+
+const char *
+xmlrpc_makePrintable_lp(const char * const input,
+                        size_t       const inputLength) {
+/*----------------------------------------------------------------------------
+   Convert an arbitrary string of characters in length-pointer form to
+   printable ASCII.  E.g. convert newlines to "\n".
+
+   Return the result in newly malloc'ed storage.  Return NULL if we can't
+   get the storage.
+-----------------------------------------------------------------------------*/
+    char * output;
+
+    output = malloc(inputLength*4+1);
+        /* Worst case, we render a character like \x01 -- 4 characters */
+
+    if (output != NULL) {
+        unsigned int inputCursor, outputCursor;
+
+        for (inputCursor = 0, outputCursor = 0; 
+             inputCursor < inputLength; 
+             ++inputCursor) {
+
+            if (isprint(input[inputCursor]))
+                output[outputCursor++] = input[inputCursor]; 
+            else if (input[inputCursor] == '\n') {
+                output[outputCursor++] = '\\';
+                output[outputCursor++] = 'n';
+            } else if (input[inputCursor] == '\t') {
+                output[outputCursor++] = '\\';
+                output[outputCursor++] = 't';
+            } else if (input[inputCursor] == '\a') {
+                output[outputCursor++] = '\\';
+                output[outputCursor++] = 'a';
+            } else if (input[inputCursor] == '\r') {
+                output[outputCursor++] = '\\';
+                output[outputCursor++] = 'r';
+            } else if (input[inputCursor] == '\\') {
+                output[outputCursor++] = '\\';
+                output[outputCursor++] = '\\';
+            } else {
+                snprintf(&output[outputCursor], 5, "\\x%02x", 
+                         input[inputCursor]);
+                outputCursor += 4;
+            }
+        }
+        output[outputCursor++] = '\0';
+    }
+    return output;
+}
+
+
+
+const char * 
+xmlrpc_makePrintable(const char * const input) {
+/*----------------------------------------------------------------------------
+   Convert an arbitrary string of characters (NUL-terminated, though) to
+   printable ASCII.  E.g. convert newlines to "\n".
+
+   Return the result in newly malloc'ed storage.  Return NULL if we can't
+   get the storage.
+-----------------------------------------------------------------------------*/
+    return xmlrpc_makePrintable_lp(input, strlen(input));
+}
+
+
+
+const char *
+xmlrpc_makePrintableChar(char const input) {
+/*----------------------------------------------------------------------------
+   Return an ASCIIZ string consisting of the character 'input',
+   properly escaped so as to be printable.  E.g., in C notation, '\n'
+   turns into "\\n"
+-----------------------------------------------------------------------------*/
+    const char * retval;
+
+    if (input == '\0')
+        retval = strdup("\\0");
+    else {
+        char buffer[2];
+        
+        buffer[0] = input;
+        buffer[1] = '\0';
+        
+        retval = xmlrpc_makePrintable(buffer);
+    }
+    return retval;
+}
diff --git a/lib/libutil/memblock.c b/lib/libutil/memblock.c
new file mode 100644 (file)
index 0000000..d79d4ca
--- /dev/null
@@ -0,0 +1,214 @@
+/* Copyright information is at end of file */
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "xmlrpc-c/util_int.h"
+#include "xmlrpc-c/util.h"
+
+#ifdef EFENCE
+        /* when looking for corruption don't allocate extra slop */
+#define BLOCK_ALLOC_MIN (1)
+#else
+#define BLOCK_ALLOC_MIN (16)
+#endif
+#define BLOCK_ALLOC_MAX (128 * 1024 * 1024)
+
+
+xmlrpc_mem_block * 
+xmlrpc_mem_block_new(xmlrpc_env * const env, 
+                     size_t       const size) {
+
+    xmlrpc_mem_block* block;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+
+    block = (xmlrpc_mem_block*) malloc(sizeof(xmlrpc_mem_block));
+    XMLRPC_FAIL_IF_NULL(block, env, XMLRPC_INTERNAL_ERROR,
+                        "Can't allocate memory block");
+
+    xmlrpc_mem_block_init(env, block, size);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+                     cleanup:
+    if (env->fault_occurred) {
+        if (block)
+            free(block);
+        return NULL;
+    } else {
+        return block;
+    }
+}
+
+/* Destroy an existing xmlrpc_mem_block, and everything it contains. */
+void
+xmlrpc_mem_block_free(xmlrpc_mem_block * const blockP) {
+
+    XMLRPC_ASSERT(blockP != NULL);
+    XMLRPC_ASSERT(blockP->_block != NULL);
+
+    xmlrpc_mem_block_clean(blockP);
+    free(blockP);
+}
+
+
+
+/* Initialize the contents of the provided xmlrpc_mem_block. */
+void
+xmlrpc_mem_block_init(xmlrpc_env *       const envP,
+                      xmlrpc_mem_block * const blockP,
+                      size_t             const size) {
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(blockP != NULL);
+
+    blockP->_size = size;
+    if (size < BLOCK_ALLOC_MIN)
+        blockP->_allocated = BLOCK_ALLOC_MIN;
+    else
+        blockP->_allocated = size;
+
+    blockP->_block = (void*) malloc(blockP->_allocated);
+    if (!blockP->_block)
+        xmlrpc_faultf(envP, "Can't allocate %u-byte memory block",
+                      blockP->_allocated);
+}
+
+
+
+/* Deallocate the contents of the provided xmlrpc_mem_block, but not
+   the block itself.
+*/
+void
+xmlrpc_mem_block_clean(xmlrpc_mem_block * const blockP) {
+
+    XMLRPC_ASSERT(blockP != NULL);
+    XMLRPC_ASSERT(blockP->_block != NULL);
+
+    free(blockP->_block);
+    blockP->_block = XMLRPC_BAD_POINTER;
+}
+
+
+
+/* Get the size of the xmlrpc_mem_block. */
+size_t 
+xmlrpc_mem_block_size(const xmlrpc_mem_block * const blockP) {
+
+    XMLRPC_ASSERT(blockP != NULL);
+    return blockP->_size;
+}
+
+
+
+/* Get the contents of the xmlrpc_mem_block. */
+void * 
+xmlrpc_mem_block_contents(const xmlrpc_mem_block * const blockP) {
+
+    XMLRPC_ASSERT(blockP != NULL);
+    return blockP->_block;
+}
+
+
+
+/* Resize an xmlrpc_mem_block, preserving as much of the contents as
+   possible.
+*/
+void 
+xmlrpc_mem_block_resize (xmlrpc_env *       const envP,
+                         xmlrpc_mem_block * const blockP,
+                         size_t             const size) {
+
+    size_t proposed_alloc;
+    void* new_block;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(blockP != NULL);
+
+    /* Check to see if we already have enough space. Maybe we'll get lucky. */
+    if (size <= blockP->_allocated) {
+        blockP->_size = size;
+        return;
+    }
+
+    /* Calculate a new allocation size. */
+#ifdef EFENCE
+    proposed_alloc = size;
+#else
+    proposed_alloc = blockP->_allocated;
+    while (proposed_alloc < size && proposed_alloc <= BLOCK_ALLOC_MAX)
+        proposed_alloc *= 2;
+#endif /* DEBUG_MEM_ERRORS */
+
+    if (proposed_alloc > BLOCK_ALLOC_MAX)
+        XMLRPC_FAIL(envP, XMLRPC_INTERNAL_ERROR, "Memory block too large");
+
+    /* Allocate our new memory block. */
+    new_block = (void*) malloc(proposed_alloc);
+    XMLRPC_FAIL_IF_NULL(new_block, envP, XMLRPC_INTERNAL_ERROR,
+                        "Can't resize memory block");
+
+    /* Copy over our data and update the xmlrpc_mem_block struct. */
+    memcpy(new_block, blockP->_block, blockP->_size);
+    free(blockP->_block);
+    blockP->_block     = new_block;
+    blockP->_size      = size;
+    blockP->_allocated = proposed_alloc;
+
+ cleanup:
+    return;
+}
+
+
+
+void 
+xmlrpc_mem_block_append(xmlrpc_env *       const envP,
+                        xmlrpc_mem_block * const blockP,
+                        const void *       const data, 
+                        size_t             const len) {
+
+    int size;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(blockP != NULL);
+
+    size = blockP->_size;
+    xmlrpc_mem_block_resize(envP, blockP, size + len);
+    XMLRPC_FAIL_IF_FAULT(envP);
+
+    memcpy(((unsigned char*) blockP->_block) + size, data, len);
+
+ cleanup:
+    return;
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
diff --git a/lib/libutil/resource.c b/lib/libutil/resource.c
new file mode 100644 (file)
index 0000000..08743d0
--- /dev/null
@@ -0,0 +1,31 @@
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/util.h"
+
+
+/*=========================================================================
+**  Resource Limits
+**=========================================================================
+*/ 
+
+static size_t limits[XMLRPC_LAST_LIMIT_ID + 1] = {
+    XMLRPC_NESTING_LIMIT_DEFAULT,
+    XMLRPC_XML_SIZE_LIMIT_DEFAULT
+};
+
+void
+xmlrpc_limit_set (int    const limit_id,
+                  size_t const value) {
+
+    XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID);
+    limits[limit_id] = value;
+}
+
+
+
+size_t
+xmlrpc_limit_get(int const limit_id) {
+
+    XMLRPC_ASSERT(0 <= limit_id && limit_id <= XMLRPC_LAST_LIMIT_ID);
+    return limits[limit_id];
+}
diff --git a/lib/libutil/sleep.c b/lib/libutil/sleep.c
new file mode 100644 (file)
index 0000000..379be0c
--- /dev/null
@@ -0,0 +1,18 @@
+#include "xmlrpc-c/sleep_int.h"
+
+#ifdef WIN32
+#include <process.h>
+#else
+#include <unistd.h>
+#endif
+
+
+void
+xmlrpc_millisecond_sleep(unsigned int const milliseconds) {
+
+#ifdef WIN32
+    Sleep(milliseconds);
+#else
+    usleep(milliseconds * 1000);
+#endif
+}
diff --git a/lib/libwww_transport/Makefile b/lib/libwww_transport/Makefile
new file mode 100644 (file)
index 0000000..acfcd66
--- /dev/null
@@ -0,0 +1,45 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+
+include $(SRCDIR)/Makefile.config
+
+LIBWWW_INCLUDES := $(shell libwww-config --cflags)
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+LDFLAGS = $(LADD)
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
+  $(LIBWWW_INCLUDES)
+
+default: all
+
+.PHONY: all
+all: xmlrpc_libwww_transport.lo
+
+.PHONY: clean
+clean: clean-common
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: tags
+tags: TAGS
+
+.PHONY: distdir
+distdir:
+
+.PHONY: install
+install:
+
+.PHONY: dep
+dep: dep-common
+
+include $(SRCDIR)/Makefile.common
+
+include Makefile.depend
+
+xmlrpc_libwww_transport.lo:%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+
diff --git a/lib/libwww_transport/Makefile.depend b/lib/libwww_transport/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/libwww_transport/xmlrpc_libwww_transport.c b/lib/libwww_transport/xmlrpc_libwww_transport.c
new file mode 100644 (file)
index 0000000..61d16ac
--- /dev/null
@@ -0,0 +1,937 @@
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/client_int.h"
+
+/* The libwww interface */
+
+/* These headers mistakenly define the macro PACKAGE.  As
+   xmlrpc_config.h already defines PACKAGE according to the package we're
+   actually part of, this causes a conflict.  So we undef here and then
+   to avoid possible problems with an incorrect PACKAGE, we undef it again
+   after.
+*/
+#undef PACKAGE
+#include "WWWLib.h"
+#include "WWWHTTP.h"
+#include "WWWInit.h"
+#undef PACKAGE
+
+/* Include our libwww SSL headers, if available. */
+#if HAVE_LIBWWW_SSL
+#include "WWWSSL.h"
+#endif
+
+#include "xmlrpc_libwww_transport.h"
+
+/* This value was discovered by Rick Blair. His efforts shaved two seconds
+** off of every request processed. Many thanks. */
+#define SMALLEST_LEGAL_LIBWWW_TIMEOUT (21)
+
+#define XMLRPC_CLIENT_USE_TIMEOUT   (2)
+
+
+struct xmlrpc_client_transport {
+    int saved_flags;
+    HTList *xmlrpc_conversions;
+    void * cookieJarP;
+        /* This is a collection of all the cookies that servers have set
+           via responses to prior requests.  It's not implemented today.
+        */
+    bool tracingOn;
+};
+
+static struct xmlrpc_client_transport clientTransport;
+
+
+typedef struct {
+/*----------------------------------------------------------------------------
+   This object represents one RPC.
+-----------------------------------------------------------------------------*/
+    struct xmlrpc_client_transport * clientTransportP;
+
+    /* These fields are used when performing synchronous calls. */
+    bool is_done;
+    int http_status;
+
+    /* Low-level information used by libwww. */
+    HTRequest *      request;
+    HTChunk *        response_data;
+    HTParentAnchor * source_anchor;
+    HTAnchor *       dest_anchor;
+
+    xmlrpc_transport_asynch_complete complete;
+    struct xmlrpc_call_info * callInfoP; 
+} rpc;
+
+
+
+static void
+createCookieJar(xmlrpc_env * const envP ATTR_UNUSED,
+                void **      const cookieJarP ATTR_UNUSED) {
+
+    /* Cookies not implemented yet */
+}
+
+
+
+static void
+destroyCookieJar(void * cookieJarP ATTR_UNUSED) {
+
+    /* Cookies not implemented yet */
+}
+
+
+
+static void
+initLibwww(const char * const appname,
+           const char * const appversion) {
+    
+    /* We initialize the library using a robot profile, because we don't
+    ** care about redirects or HTTP authentication, and we want to
+    ** reduce our application footprint as much as possible. */
+    HTProfile_newRobot(appname, appversion);
+
+    /* Ilya Goldberg <igg@mit.edu> provided the following code to access
+    ** SSL-protected servers. */
+#if HAVE_LIBWWW_SSL
+    /* Set the SSL protocol method. By default, it is the highest
+    ** available protocol. Setting it up to SSL_V23 allows the client
+    ** to negotiate with the server and set up either TSLv1, SSLv3,
+    ** or SSLv2 */
+    HTSSL_protMethod_set(HTSSL_V23);
+    
+    /* Set the certificate verification depth to 2 in order to be able to
+    ** validate self-signed certificates */
+    HTSSL_verifyDepth_set(2);
+    
+    /* Register SSL stuff for handling ssl access. The parameter we pass
+    ** is NO because we can't be pre-emptive with POST */
+    HTSSLhttps_init(NO);
+#endif /* HAVE_LIBWWW_SSL */
+    
+    /* For interoperability with Frontier, we need to tell libwww *not*
+    ** to send 'Expect: 100-continue' headers. But if we're not sending
+    ** these, we shouldn't wait for them. So set our built-in delays to
+    ** the smallest legal values. */
+    HTTP_setBodyWriteDelay (SMALLEST_LEGAL_LIBWWW_TIMEOUT,
+                            SMALLEST_LEGAL_LIBWWW_TIMEOUT);
+    
+    /* We attempt to disable all of libwww's chatty, interactive
+    ** prompts. Let's hope this works. */
+    HTAlert_setInteractive(NO);
+    
+    /* Here are some alternate setup calls which will help greatly
+    ** with debugging, should the need arise.
+    **
+    ** HTProfile_newNoCacheClient(appname, appversion);
+    ** HTAlert_setInteractive(YES);
+    ** HTPrint_setCallback(printer);
+    ** HTTrace_setCallback(tracer); */
+}
+
+
+
+static void 
+create(xmlrpc_env *                      const envP,
+       int                               const flags,
+       const char *                      const appname,
+       const char *                      const appversion,
+       const struct xmlrpc_xportparms *  const transportParmsP ATTR_UNUSED,
+       size_t                            const parm_size ATTR_UNUSED,
+       struct xmlrpc_client_transport ** const handlePP) {
+/*----------------------------------------------------------------------------
+   This does the 'create' operation for a Libwww client transport.
+-----------------------------------------------------------------------------*/
+    /* The Libwww transport is not re-entrant -- you can have only one
+       per program instance.  Even if we changed the Xmlrpc-c code not
+       to use global variables, that wouldn't help because Libwww
+       itself is not re-entrant.  
+       
+       So we use a global variable ('clientTransport') for our transport state.
+    */
+    struct xmlrpc_client_transport * const clientTransportP = &clientTransport;
+    *handlePP = clientTransportP;
+
+    clientTransportP->saved_flags = flags;
+
+    createCookieJar(envP, &clientTransportP->cookieJarP);
+    if (!envP->fault_occurred) {
+        if (!(clientTransportP->saved_flags & 
+              XMLRPC_CLIENT_SKIP_LIBWWW_INIT))
+            initLibwww(appname, appversion);
+
+        /* Set up our list of conversions for XML-RPC requests. This is a
+        ** massively stripped-down version of the list in libwww's HTInit.c.
+        ** XXX - This is hackish; 10.0 is an arbitrary, large quality factor
+        ** designed to override the built-in converter for XML. */
+        clientTransportP->xmlrpc_conversions = HTList_new();
+        HTConversion_add(clientTransportP->xmlrpc_conversions, 
+                         "text/xml", "*/*",
+                         HTThroughLine, 10.0, 0.0, 0.0);
+
+        if (envP->fault_occurred)
+            destroyCookieJar(clientTransportP->cookieJarP);
+    }
+    if (getenv("XMLRPC_LIBWWW_TRACE"))
+        clientTransportP->tracingOn = TRUE;
+    else
+        clientTransportP->tracingOn = FALSE;
+}
+
+
+
+static void 
+destroy(struct xmlrpc_client_transport * const clientTransportP) {
+/*----------------------------------------------------------------------------
+   This does the 'destroy' operation for a Libwww client transport.
+-----------------------------------------------------------------------------*/
+    XMLRPC_ASSERT(clientTransportP != NULL);
+
+    if (!(clientTransportP->saved_flags & XMLRPC_CLIENT_SKIP_LIBWWW_INIT)) {
+        HTProfile_delete();
+    }
+    destroyCookieJar(clientTransportP->cookieJarP);
+}
+
+
+
+/*=========================================================================
+**  HTTP Error Reporting
+**=======================================================================*/
+
+static void
+formatLibwwwError(HTRequest *   const requestP,
+                  const char ** const msgP) {
+/*----------------------------------------------------------------------------
+   When something fails in a Libwww request, Libwww generates a stack
+   of error information (precious little information, of course, in the
+   Unix tradition) and attaches it to the request object.  We make a message
+   out of that information.
+
+   We rely on Libwww's HTDialog_errorMessage() to do the bulk of the
+   formatting; we might be able to coax more information out of the request
+   if we interpreted the error stack directly.
+-----------------------------------------------------------------------------*/
+    HTList * const errStack = HTRequest_error(requestP);
+    
+    if (errStack == NULL)
+        xmlrpc_asprintf(msgP, "Libwww supplied no error details");
+    else {
+        /* Get an error message from libwww.  The middle three
+           parameters to HTDialog_errorMessage appear to be ignored.
+           XXX - The documentation for this API is terrible, so we may
+           be using it incorrectly.  
+        */
+        const char * msg =
+            HTDialog_errorMessage(requestP, HT_A_MESSAGE, HT_MSG_NULL,
+                                  "An error occurred", errStack);
+        
+        if (msg == NULL)
+            xmlrpc_asprintf(msgP, "Libwww supplied some error detail, "
+                            "but its HTDialog_errorMessage() subroutine "
+                            "mysteriously failed to interpret it for us.");
+        else
+            *msgP = msg;
+    }
+}
+
+
+
+static void 
+set_fault_from_http_request(xmlrpc_env * const envP,
+                            int          const status,
+                            HTRequest *  const requestP) {
+/*----------------------------------------------------------------------------
+   Assuming 'requestP' identifies a completed libwww HTTP request, set
+   *envP according to its success/error status.
+-----------------------------------------------------------------------------*/
+    XMLRPC_ASSERT_PTR_OK(requestP);
+
+    if (status == 200) {
+        /* No error.  Don't set one in *envP */
+    } else {
+        const char * libwwwMsg;
+        formatLibwwwError(requestP, &libwwwMsg);
+
+        if (status == -1)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_NETWORK_ERROR,
+                "Unable to complete the HTTP request.  %s", libwwwMsg);
+        else {
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_NETWORK_ERROR,
+                "HTTP request completed with HTTp error %d.  %s",
+                status, libwwwMsg);
+        }
+        xmlrpc_strfree(libwwwMsg);
+    }
+}
+
+
+
+static BOOL 
+setCookie(HTRequest * const request,
+          HTCookie *  const cookieP ATTR_UNUSED,
+          void *      const param ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+  This is the callback from libwww to tell us the server (according to
+  its response) wants us to store a cookie (and include it in future
+  requests).
+
+  We assume that the cookies "domain" is the server's host name
+  (there are options on the libwww connection to make libwww call this
+  callback only when that's the case).
+-----------------------------------------------------------------------------*/
+    rpc * const rpcP = HTRequest_context(request);
+    struct xmlrpc_client_transport * const clientTransportP = 
+        rpcP->clientTransportP;
+
+    BOOL retval;
+
+    /* Avoid unused variable warning */
+    if (clientTransportP->cookieJarP == clientTransportP->cookieJarP) {}
+    /* Cookies are not implemented today */
+    retval = NO;
+
+    return retval;
+}
+
+
+
+static HTAssocList *
+cookiesForHost(const char * const host ATTR_UNUSED,
+               void *       const cookieJarP ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+  Find and return all the cookies in jar 'cookieJarP' that are for the
+  host 'host'.
+-----------------------------------------------------------------------------*/
+    HTAssocList * hisCookiesP;
+
+    hisCookiesP = HTAssocList_new();
+
+    if (hisCookiesP) {
+        /* Cookies are not implemented yet */
+        /* Library/Examples/cookie.c in the w3c-libwww source tree contains
+           an example of constructing the cookie list we are supposed to
+           return.  But today, we return an empty list.
+        */
+    }
+    return hisCookiesP;
+}
+
+
+
+static HTAssocList *
+findCookie(HTRequest * const request,
+           void *      const param ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+  This is the callback from libwww to get the cookies to include in a
+  request (presumably values the server set via a prior response).
+-----------------------------------------------------------------------------*/
+    rpc * const rpcP = HTRequest_context(request);
+    struct xmlrpc_client_transport * const clientTransportP = 
+        rpcP->clientTransportP;
+    const char * const addr = 
+        HTAnchor_address((HTAnchor *) HTRequest_anchor(request));
+    const char * const host = HTParse(addr, "", PARSE_HOST);
+
+    return cookiesForHost(host, clientTransportP->cookieJarP);
+}
+
+
+
+static void 
+deleteSourceAnchor(HTParentAnchor * const anchor) {
+
+    /* We need to clear the document first, or else libwww won't
+    ** really delete the anchor. */
+    HTAnchor_setDocument(anchor, NULL);
+
+    /* XXX - Deleting this anchor causes HTLibTerminate to dump core. */
+    /* HTAnchor_delete(anchor); */
+}
+
+
+
+static void
+createSourceAnchor(xmlrpc_env *       const envP,
+                   HTParentAnchor **  const sourceAnchorPP,
+                   xmlrpc_mem_block * const xmlP) {
+
+    HTParentAnchor * const sourceAnchorP = HTTmpAnchor(NULL);
+
+    if (sourceAnchorP == NULL)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, 
+            "Unable to build source anchor.  HTTmpAnchor() failed.");
+    else {
+        HTAnchor_setDocument(sourceAnchorP,
+                             XMLRPC_MEMBLOCK_CONTENTS(char, xmlP));
+        HTAnchor_setFormat(sourceAnchorP, HTAtom_for("text/xml"));
+        HTAnchor_setLength(sourceAnchorP, XMLRPC_MEMBLOCK_SIZE(char, xmlP));
+
+        *sourceAnchorPP = sourceAnchorP;
+    }
+}
+
+
+
+static void
+createDestAnchor(xmlrpc_env *               const envP,
+                 HTAnchor **                const destAnchorPP,
+                 const xmlrpc_server_info * const serverP) {
+                 
+    *destAnchorPP = HTAnchor_findAddress(serverP->_server_url);
+
+    if (*destAnchorPP == NULL)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "Could not build destination anchor.  HTAnchor_findAddress() "
+            "failed.");
+}
+
+
+
+static void
+rpcCreate(xmlrpc_env *                       const envP,
+          struct xmlrpc_client_transport *   const clientTransportP,
+          const xmlrpc_server_info *         const serverP,
+          xmlrpc_mem_block *                 const xmlP,
+          xmlrpc_transport_asynch_complete         complete, 
+          struct xmlrpc_call_info *          const callInfoP,
+          rpc **                             const rpcPP) {
+
+    rpc *rpcP;
+    HTRqHd request_headers;
+    HTStream *target_stream;
+
+    /* Allocate our structure. */
+    MALLOCVAR(rpcP);
+    XMLRPC_FAIL_IF_NULL(rpcP, envP, XMLRPC_INTERNAL_ERROR,
+                        "Out of memory in rpcCreate()");
+
+    /* Set up our basic members. */
+    rpcP->clientTransportP = clientTransportP;
+    rpcP->is_done = FALSE;
+    rpcP->http_status = 0;
+    rpcP->complete = complete;
+    rpcP->callInfoP = callInfoP;
+
+    /* Start cookie handler. */
+    HTCookie_init();
+    HTCookie_setCallbacks(setCookie, NULL, findCookie, NULL);
+    HTCookie_setCookieMode(HT_COOKIE_ACCEPT | 
+                           HT_COOKIE_SEND | 
+                           HT_COOKIE_SAME_HOST);
+
+    /* Cookies aren't implemented today; reset. */
+    HTCookie_setCookieMode(0);
+    
+    /* Create a HTRequest object. */
+    rpcP->request = HTRequest_new();
+    XMLRPC_FAIL_IF_NULL(rpcP, envP, XMLRPC_INTERNAL_ERROR,
+                        "HTRequest_new failed");
+    
+    /* Install ourselves as the request context. */
+    HTRequest_setContext(rpcP->request, rpcP);
+
+    /* XXX - Disable the 'Expect:' header so we can talk to Frontier. */
+    request_headers = HTRequest_rqHd(rpcP->request);
+    request_headers = request_headers & ~HT_C_EXPECT;
+    HTRequest_setRqHd(rpcP->request, request_headers);
+
+    /* Send an authorization header if we need one. */
+    if (serverP->_http_basic_auth)
+        HTRequest_addCredentials(rpcP->request, "Authorization",
+                                 serverP->_http_basic_auth);
+    
+    /* Make sure there is no XML conversion handler to steal our data.
+    ** The 'override' parameter is currently ignored by libwww, so our
+    ** list of conversions must be designed to co-exist with the built-in
+    ** conversions. */
+    HTRequest_setConversion(rpcP->request, 
+                            clientTransportP->xmlrpc_conversions, NO);
+
+    /* Set up our response buffer. */
+    target_stream = HTStreamToChunk(rpcP->request, &rpcP->response_data, 0);
+    XMLRPC_FAIL_IF_NULL(rpcP->response_data, envP, XMLRPC_INTERNAL_ERROR,
+                        "HTStreamToChunk failed");
+    XMLRPC_ASSERT(target_stream != NULL);
+    HTRequest_setOutputStream(rpcP->request, target_stream);
+    HTRequest_setOutputFormat(rpcP->request, WWW_SOURCE);
+
+    createSourceAnchor(envP, &rpcP->source_anchor, xmlP);
+
+    if (!envP->fault_occurred) {
+        createDestAnchor(envP, &rpcP->dest_anchor, serverP);
+
+        if (envP->fault_occurred)
+            /* See below for comments about deleting the source and dest
+            ** anchors. This is a bit of a black art. */
+            deleteSourceAnchor(rpcP->source_anchor);
+    }
+    
+ cleanup:
+    if (envP->fault_occurred) {
+        if (rpcP) {
+            if (rpcP->request)
+                HTRequest_delete(rpcP->request);
+            if (rpcP->response_data)
+                HTChunk_delete(rpcP->response_data);
+            free(rpcP);
+        }
+    }
+    *rpcPP = rpcP;
+}
+
+
+
+static void 
+rpcDestroy(rpc * const rpcP) {
+
+    XMLRPC_ASSERT_PTR_OK(rpcP);
+    XMLRPC_ASSERT(rpcP->request != XMLRPC_BAD_POINTER);
+    XMLRPC_ASSERT(rpcP->response_data != XMLRPC_BAD_POINTER);
+
+    /* Junji Kanemaru reports on 05.04.11 that with asynch calls, he
+       get a segfault, and reversing the order of deleting the request
+       and the response chunk buffer cured it.  But we find no reason
+       that should be so, so we're waiting for someone to arrive at an
+       explanation before changing anything.  HTRequest_delete() does
+       destroy the output stream, and the output stream refers to the
+       response chunk, but HTRequest_delete() explicitly refrains from
+       destroying the response chunk.  And the response chunk does not
+       refer to the request.
+    */
+
+    HTRequest_delete(rpcP->request);
+    rpcP->request = XMLRPC_BAD_POINTER;
+    HTChunk_delete(rpcP->response_data);
+    rpcP->response_data = XMLRPC_BAD_POINTER;
+
+    /* This anchor points to private data, so we're allowed to delete it.  */
+    deleteSourceAnchor(rpcP->source_anchor);
+
+    /* WARNING: We can't delete the destination anchor, because this points
+    ** to something in the outside world, and lives in a libwww hash table.
+    ** Under certain circumstances, this anchor may have been reissued to
+    ** somebody else. So over time, the anchor cache will grow. If this
+    ** is a problem for your application, read the documentation for
+    ** HTAnchor_deleteAll.
+    **
+    ** However, we CAN check to make sure that no documents have been
+    ** attached to the anchor. This assertion may fail if you're using
+    ** libwww for something else, so please feel free to comment it out. */
+    /* XMLRPC_ASSERT(HTAnchor_document(rpcP->dest_anchor) == NULL);
+     */
+
+    HTCookie_deleteCallbacks();
+    HTCookie_terminate();
+
+    free(rpcP);
+}
+
+
+
+static void
+extract_response_chunk(xmlrpc_env *        const envP,
+                       rpc *               const rpcP,
+                       xmlrpc_mem_block ** const responseXmlPP) {
+
+    /* Check to make sure that w3c-libwww actually sent us some data.
+    ** XXX - This may happen if libwww is shut down prematurely, believe it
+    ** or not--we'll get a 200 OK and no data. Gag me with a bogus design
+    ** decision. This may also fail if some naughty libwww converter
+    ** ate our data unexpectedly. */
+    if (!HTChunk_data(rpcP->response_data))
+        xmlrpc_env_set_fault(envP, XMLRPC_NETWORK_ERROR,
+                             "w3c-libwww returned no data");
+    else {
+        *responseXmlPP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+        if (!envP->fault_occurred) {
+            if (rpcP->clientTransportP->tracingOn) {
+                fprintf(stderr, "HTTP chunk received: %u bytes: '%.*s'",
+                        HTChunk_size(rpcP->response_data),
+                        HTChunk_size(rpcP->response_data),
+                        HTChunk_data(rpcP->response_data));
+            }
+
+            XMLRPC_MEMBLOCK_APPEND(char, envP, *responseXmlPP,
+                                   HTChunk_data(rpcP->response_data),
+                                   HTChunk_size(rpcP->response_data));
+            if (envP->fault_occurred)
+                XMLRPC_MEMBLOCK_FREE(char, *responseXmlPP);
+        }
+    }
+}
+
+
+
+static int 
+synch_terminate_handler(HTRequest *  const request,
+                        HTResponse * const response ATTR_UNUSED,
+                        void *       const param ATTR_UNUSED,
+                        int          const status) {
+/*----------------------------------------------------------------------------
+   This is a libwww request completion handler.
+
+   HTEventList_newLoop() calls this when it completes a request (with this
+   registered as the completion handler).
+-----------------------------------------------------------------------------*/
+    rpc *rpcP;
+
+    rpcP = HTRequest_context(request);
+
+    rpcP->is_done = TRUE;
+    rpcP->http_status = status;
+
+    HTEventList_stopLoop();
+
+    return HT_OK;
+}
+
+
+
+static void
+call(xmlrpc_env *                     const envP,
+     struct xmlrpc_client_transport * const clientTransportP,
+     const xmlrpc_server_info *       const serverP,
+     xmlrpc_mem_block *               const xmlP,
+     xmlrpc_mem_block **              const responsePP) {
+/*----------------------------------------------------------------------------
+   This does the 'call' operation for a Libwww client transport.
+-----------------------------------------------------------------------------*/
+    rpc * rpcP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(serverP);
+    XMLRPC_ASSERT_PTR_OK(xmlP);
+    XMLRPC_ASSERT_PTR_OK(responsePP);
+
+    rpcCreate(envP, clientTransportP, serverP, xmlP, NULL, NULL, &rpcP);
+    if (!envP->fault_occurred) {
+        int ok;
+        
+        /* Install our request handler. */
+        HTRequest_addAfter(rpcP->request, &synch_terminate_handler, 
+                           NULL, NULL, HT_ALL, HT_FILTER_LAST, NO);
+
+        /* Start our request running. */
+        ok = HTPostAnchor(rpcP->source_anchor, 
+                          rpcP->dest_anchor, 
+                          rpcP->request);
+        if (!ok)
+            xmlrpc_env_set_fault(
+                envP, XMLRPC_NETWORK_ERROR,
+                "Libwww HTPostAnchor() failed to start POST request");
+        else {
+            /* Run our event-processing loop.  HTEventList_newLoop()
+               is what calls synch_terminate_handler(), by virtue of
+               it being registered as a handler.  It may return for
+               other reasons than the request being complete, though.
+               so we call it in a loop until synch_terminate_handler()
+               really has been called.
+            */
+            while (!rpcP->is_done)
+                HTEventList_newLoop();
+        
+            /* Fail if we didn't get a "200 OK" response from the server */
+            if (rpcP->http_status != 200)
+                set_fault_from_http_request(
+                    envP, rpcP->http_status, 
+                    rpcP->request);
+            else {
+                /* XXX - Check to make sure response type is text/xml here. */
+                
+                extract_response_chunk(envP, rpcP, responsePP);
+            }
+        }
+        rpcDestroy(rpcP);
+    }
+}
+
+
+
+/*=========================================================================
+**  Event Loop
+**=========================================================================
+**  We manage a fair bit of internal state about our event loop. This is
+**  needed to determine when (and if) we should exit the loop.
+*/
+
+static int outstanding_asynch_calls = 0;
+static int event_loop_flags = 0;
+static int timer_called = 0;
+
+static void 
+register_asynch_call(void) {
+    XMLRPC_ASSERT(outstanding_asynch_calls >= 0);
+    outstanding_asynch_calls++;
+}
+
+
+
+static void 
+unregister_asynch_call(void) {
+
+    XMLRPC_ASSERT(outstanding_asynch_calls > 0);
+    outstanding_asynch_calls--;
+    if (outstanding_asynch_calls == 0)
+        HTEventList_stopLoop();
+}
+
+
+
+static int 
+timer_callback(HTTimer *   const timer     ATTR_UNUSED,
+               void *      const user_data ATTR_UNUSED,
+               HTEventType const event     ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+  A handy timer callback which cancels the running event loop. 
+-----------------------------------------------------------------------------*/
+    XMLRPC_ASSERT(event == HTEvent_TIMEOUT);
+    timer_called = 1;
+    HTEventList_stopLoop();
+    
+    /* XXX - The meaning of this return value is undocumented, but close
+    ** inspection of libwww's source suggests that we want to return HT_OK. */
+    return HT_OK;
+}
+
+
+
+static void 
+eventLoopRun(int            const flags, 
+             xmlrpc_timeout const milliseconds) {
+/*----------------------------------------------------------------------------
+   Process all responses from outstanding requests as they come in.
+   Return when there are no more outstanding responses.
+
+   Or, if 'flags' has the XMLRPC_CLIENT_USE_TIMEOUT flag set, return
+   when 'milliseconds' milliseconds have elapsed, regardless of whether
+   there are still outstanding responses.
+
+   The processing we do consists of telling libwww to process the
+   completion of the libwww request.  That normally includes calling
+   the xmlrpc_libwww_transport request termination handler, because
+   the submitter of the libwww request would have registered that as a
+   callback.
+-----------------------------------------------------------------------------*/
+    if (outstanding_asynch_calls > 0) {
+        HTTimer *timer;
+
+        event_loop_flags = flags;
+        
+        /* Run an appropriate event loop.  The HTEeventList_newLoop()
+           is what calls asynch_terminate_handler(), by virtue of it
+           being registered as a handler.
+        */
+        if (event_loop_flags & XMLRPC_CLIENT_USE_TIMEOUT) {
+            
+            /* Run our event loop with a timer. Note that we need to be very
+            ** careful about race conditions--timers can be fired in either
+            ** HTimer_new or HTEventList_newLoop. And if our callback were to
+            ** get called before we entered the loop, we would never exit.
+            ** So we use a private flag of our own--we can't even rely on
+            ** HTTimer_hasTimerExpired, because that only checks the time,
+            ** not whether our callback has been run. Yuck. */
+            timer_called = 0;
+            timer = HTTimer_new(NULL, &timer_callback, NULL,
+                                milliseconds, YES, NO);
+            XMLRPC_ASSERT(timer != NULL);
+            if (!timer_called)
+                HTEventList_newLoop();
+            HTTimer_delete(timer);
+            
+        } else {
+            /* Run our event loop without a timer. */
+            HTEventList_newLoop();
+        }
+        
+        /* Reset our flags, so we don't interfere with direct calls to the
+        ** libwww event loop functions. */
+        event_loop_flags = 0;
+    } else {
+        /* There are *no* calls to process.  This may mean that none
+           of the asynch calls were ever set up, and the client's
+           callbacks have already been called with an error, or that
+           all outstanding calls were completed during a previous
+           synchronous call.  
+        */
+    }
+}
+
+
+
+static void 
+finishAsynch(
+    struct xmlrpc_client_transport * const clientTransportP ATTR_UNUSED,
+    xmlrpc_timeoutType               const timeoutType,
+    xmlrpc_timeout                   const timeout) {
+/*----------------------------------------------------------------------------
+   This does the 'finish_asynch' operation for a Libwww client transport.
+-----------------------------------------------------------------------------*/
+    eventLoopRun(timeoutType == timeout_yes ? XMLRPC_CLIENT_USE_TIMEOUT : 0,
+                 timeout);
+}
+
+
+
+static int 
+asynch_terminate_handler(HTRequest *  const request,
+                         HTResponse * const response ATTR_UNUSED,
+                         void *       const param ATTR_UNUSED,
+                         int          const status) {
+/*----------------------------------------------------------------------------
+   Handle the completion of a libwww request.
+
+   This is the bottom half of the xmlrpc_libwww_transport asynchronous
+   call dispatcher.  It's what the dispatcher registers with libwww as
+   a "local after filter" so that libwww calls it when a request that
+   xmlrpc_libwww_transport submitted to it is complete.
+
+   We destroy the RPC, including the request which is our argument.
+   Strange as that may seem, it is apparently legal for an after filter
+   to destroy the request that was passed to it -- or not.
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+    rpc * rpcP;
+    xmlrpc_mem_block * responseXmlP;
+
+    XMLRPC_ASSERT_PTR_OK(request);
+
+    xmlrpc_env_init(&env);
+
+    rpcP = HTRequest_context(request);
+
+    /* Unregister this call from the event loop. Among other things, this
+    ** may decide to stop the event loop.
+    **/
+    unregister_asynch_call();
+
+    /* Give up if an error occurred. */
+    if (status != 200)
+        set_fault_from_http_request(&env, status, request);
+    else {
+        /* XXX - Check to make sure response type is text/xml here. */
+        extract_response_chunk(&env, rpcP, &responseXmlP);
+    }
+    rpcP->complete(rpcP->callInfoP, responseXmlP, env);
+
+    if (!env.fault_occurred)
+        XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
+
+    rpcDestroy(rpcP);
+    
+    xmlrpc_env_clean(&env);
+    return HT_OK;
+}
+
+
+
+static void 
+sendRequest(xmlrpc_env *                     const envP, 
+            struct xmlrpc_client_transport * const clientTransportP,
+            const xmlrpc_server_info *       const serverP,
+            xmlrpc_mem_block *               const xmlP,
+            xmlrpc_transport_asynch_complete       complete,
+            struct xmlrpc_call_info *        const callInfoP) {
+/*----------------------------------------------------------------------------
+   Initiate an XML-RPC rpc asynchronously.  Don't wait for it to go to
+   the server.
+
+   Unless we return failure, we arrange to have complete() called when
+   the rpc completes.
+
+   This does the 'send_request' operation for a Libwww client transport.
+-----------------------------------------------------------------------------*/
+    rpc * rpcP;
+
+    XMLRPC_ASSERT_PTR_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(serverP);
+    XMLRPC_ASSERT_PTR_OK(xmlP);
+    XMLRPC_ASSERT_PTR_OK(callInfoP);
+
+    rpcCreate(envP, clientTransportP, serverP, xmlP, complete, callInfoP, 
+              &rpcP);
+    if (!envP->fault_occurred) {
+        int ok;
+
+        /* Install our request handler. */
+        HTRequest_addAfter(rpcP->request, &asynch_terminate_handler, 
+                           NULL, NULL, HT_ALL, HT_FILTER_LAST, NO);
+
+        /* Register our asynchronous call with the event loop.  This means
+           the user's callback is guaranteed to be called eventually.
+        */
+        register_asynch_call();
+
+        /* This makes the TCP connection and sends the XML to the server
+           as an HTTP POST request.
+
+           There was a comment here that said this might return failure
+           (!ok) and still invoke our completion handler
+           (asynch_terminate_handler().  The code attempted to deal with
+           that.  Well, it's impossible to deal with that, so if it really
+           happens, we must fix Libwww.  -Bryan 04.11.23.
+        */
+
+        ok = HTPostAnchor(rpcP->source_anchor, 
+                          rpcP->dest_anchor, 
+                          rpcP->request);
+        if (!ok) {
+            unregister_asynch_call();
+            xmlrpc_env_set_fault(envP, XMLRPC_NETWORK_ERROR,
+                                 "Libwww (HTPostAnchor()) failed to start the "
+                                 "POST request.");
+        }
+        if (envP->fault_occurred)
+            rpcDestroy(rpcP);
+    }
+}
+
+
+
+struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops = {
+    NULL,
+    NULL,
+    &create,
+    &destroy,
+    &sendRequest,
+    &call,
+    &finishAsynch,
+};
diff --git a/lib/libwww_transport/xmlrpc_libwww_transport.h b/lib/libwww_transport/xmlrpc_libwww_transport.h
new file mode 100644 (file)
index 0000000..66d8048
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef XMLRPC_LIBWWW_TRANSPORT_H
+#define XMLRPC_LIBWWW_TRANSPORT_H
+
+#include "xmlrpc-c/transport.h"
+
+extern struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops;
+
+#endif
diff --git a/lib/util/Makefile b/lib/util/Makefile
new file mode 100644 (file)
index 0000000..27ae85d
--- /dev/null
@@ -0,0 +1,52 @@
+###############################################################################
+# This directory builds object modules that provide utility functions that
+# programs can use.  Not libraries, though -- just programs.  The reason
+# we don't want any library to use object modules in here is that they'll
+# probably pollute the name space when users link those libraries to their
+# programs.  In fact, if more than one Xmlrpc-c library includes one of these
+# modules, the libraries will conflict with each other.
+#
+# So a utility function that is to be used by libraries (and, optionally,
+# programs) should go in libxmlrpc_util.  libxmlrpc_util is a prerequisite
+# for many Xmlrpc-c libraries, gets included in a program link only once,
+# and uses external symbol names that have the "xmlrpc_" prefix to avoid
+# collision with users' code.
+#
+# If we knew a portable way to link multiple object modules into one and
+# restrict the symbols exported by the whole, we could avoid this mess and
+# just link utility object modules into each Xmlrpc-c library.
+##############################################################################
+
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+SUBDIR = lib/util
+BUILDDIR = $(SRCDIR)
+
+default: all
+
+include $(BUILDDIR)/Makefile.config
+
+include $(SRCDIR)/Makefile.common
+
+.PHONY: all
+all: cmdline_parser.lo getoptx.lo casprintf.lo
+
+INCLUDES = -Iinclude -I$(BUILDDIR)
+
+CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD)
+
+%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $<
+
+include Makefile.depend
+
+.PHONY: clean distclean
+clean: clean-common
+
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
+
+install:
\ No newline at end of file
diff --git a/lib/util/Makefile.depend b/lib/util/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/util/casprintf.c b/lib/util/casprintf.c
new file mode 100644 (file)
index 0000000..8a56512
--- /dev/null
@@ -0,0 +1,93 @@
+#define _GNU_SOURCE
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "xmlrpc_config.h"  /* For HAVE_ASPRINTF, __inline__ */
+#include "casprintf.h"
+
+
+
+static __inline__ void
+simpleVasprintf(char **      const retvalP,
+                const char * const fmt,
+                va_list            varargs) {
+/*----------------------------------------------------------------------------
+   This is a poor man's implementation of vasprintf(), of GNU fame.
+-----------------------------------------------------------------------------*/
+    size_t const initialSize = 4096;
+    char * result;
+
+    result = malloc(initialSize);
+    if (result != NULL) {
+        size_t bytesNeeded;
+        bytesNeeded = vsnprintf(result, initialSize, fmt, varargs);
+        if (bytesNeeded > initialSize) {
+            free(result);
+            result = malloc(bytesNeeded);
+            if (result != NULL)
+                vsnprintf(result, bytesNeeded, fmt, varargs);
+        } else if (bytesNeeded == initialSize) {
+            if (result[initialSize-1] != '\0') {
+                /* This is one of those old systems where vsnprintf()
+                   returns the number of bytes it used, instead of the
+                   number that it needed, and it in fact needed more than
+                   we gave it.  Rather than mess with this highly unlikely
+                   case (old system and string > 4095 characters), we just
+                   treat this like an out of memory failure.
+                */
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    *retvalP = result;
+}
+
+
+
+const char * const strsol = "[Insufficient memory to build string]";
+
+
+
+void
+cvasprintf(const char ** const retvalP,
+           const char *  const fmt,
+           va_list             varargs) {
+
+    char * string;
+
+#if HAVE_ASPRINTF
+    vasprintf(&string, fmt, varargs);
+#else
+    simpleVasprintf(&string, fmt, varargs);
+#endif
+
+    if (string == NULL)
+        *retvalP = strsol;
+    else
+        *retvalP = string;
+}
+
+
+
+void GNU_PRINTF_ATTR(2,3)
+casprintf(const char ** const retvalP, const char * const fmt, ...) {
+
+    va_list varargs;  /* mysterious structure used by variable arg facility */
+
+    va_start(varargs, fmt); /* start up the mysterious variable arg facility */
+
+    cvasprintf(retvalP, fmt, varargs);
+
+    va_end(varargs);
+}
+
+
+
+void
+strfree(const char * const string) {
+
+    if (string != strsol)
+        free((void *)string);
+}
diff --git a/lib/util/cmdline_parser.c b/lib/util/cmdline_parser.c
new file mode 100644 (file)
index 0000000..a2c19ab
--- /dev/null
@@ -0,0 +1,449 @@
+#include "xmlrpc_config.h"  /* prereq for mallocvar.h -- defines __inline__ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+#include "casprintf.h"
+#include "getoptx.h"
+
+#include "cmdline_parser.h"
+
+#define MAXOPTS 100
+
+struct optionDesc {
+    const char *    name;
+    enum optiontype type;
+    bool            present;
+    union {
+        unsigned int u;
+        int          i;
+        const char * s;
+    } value;
+};
+
+
+
+struct cmdlineParserCtl {
+    struct optionDesc * optionDescArray;
+    unsigned int        numOptions;
+    const char **       argumentArray;
+    unsigned int        numArguments;
+};
+
+
+
+static struct optionx *
+createLongOptsArray(struct optionDesc * const optionDescArray,
+                    unsigned int        const numOptions) {
+
+    struct optionx * longopts; 
+
+    MALLOCARRAY(longopts, numOptions+1);
+    if (longopts != NULL) {
+        unsigned int i;
+
+        for (i = 0; i < numOptions; ++i) {
+            longopts[i].name = optionDescArray[i].name;
+            /* If the option takes a value, we say it is optional even
+               though it never is.  That's because if we say it is
+               mandatory, getopt_long_only() pretends it doesn't even
+               recognize the option if the user doesn't give a value.
+               We prefer to generate a meaningful error message when
+               the user omits a required option value.
+            */
+            longopts[i].has_arg = 
+                optionDescArray[i].type == OPTTYPE_FLAG ? 
+                no_argument : optional_argument;
+            longopts[i].flag = NULL;
+            longopts[i].val = i;
+        }
+        longopts[numOptions].name = 0;
+        longopts[numOptions].has_arg = 0;
+        longopts[numOptions].flag = 0;
+        longopts[numOptions].val = 0;
+    }
+    return longopts;
+}
+
+
+
+static void
+parseOptionValue(const char *        const optarg, 
+                 struct optionDesc * const optionP,
+                 const char **       const errorP) {
+    
+    switch (optionP->type) {
+    case OPTTYPE_UINT: 
+    case OPTTYPE_INT: {
+        if (optarg == NULL)
+            casprintf(errorP, "Option requires a value");
+        else if (strlen(optarg) == 0)
+            casprintf(errorP, "Numeric option value is null string");
+        else {
+            char * tailptr;
+            long const longvalue = strtol(optarg, &tailptr, 10);
+            if (*tailptr != '\0')
+                casprintf(errorP, "Non-numeric value "
+                         "for numeric option value: '%s'", optarg);
+            else if (errno == ERANGE || longvalue > INT_MAX)
+                casprintf(errorP, "Numeric value out of range: %s", optarg);
+            else { 
+                if (optionP->type == OPTTYPE_UINT) {
+                    if (longvalue < 0)
+                        casprintf(errorP, "Unsigned numeric value is "
+                                  "negative: %ld", longvalue);
+                    else {
+                        *errorP = NULL;
+                        optionP->value.u = (unsigned int) longvalue;
+                    }
+                } else {
+                    *errorP = NULL;
+                    optionP->value.u = (int) longvalue;
+                }
+            }
+        }
+    }
+    break;
+    case OPTTYPE_STRING:
+        if (optarg == NULL)
+            casprintf(errorP, "Option requires a value");
+        else {
+            *errorP = NULL;
+            optionP->value.s = strdup(optarg);
+        }
+        break;
+    case OPTTYPE_FLAG:
+        *errorP = NULL;
+        break;
+    }
+}
+
+
+
+static void
+processOption(struct optionDesc * const optionP,
+              const char *        const optarg,
+              const char **       const errorP) {
+
+    const char * error;
+    
+    parseOptionValue(optarg, optionP, &error);
+    if (error)
+        casprintf(errorP, "Error in '%s' option: %s", optionP->name, error);
+    else
+        optionP->present = true;
+}
+
+
+
+static void
+extractArguments(struct cmdlineParserCtl * const cpP,
+                 unsigned int              const argc,
+                 const char **             const argv) {
+    
+    cpP->numArguments = argc - getopt_argstart();
+    MALLOCARRAY(cpP->argumentArray, cpP->numArguments);
+
+    if (cpP->argumentArray == NULL) {
+        fprintf(stderr, "Unable to allocate memory for argument array\n");
+        abort();
+    } else {
+        unsigned int i;
+
+        for (i = 0; i < cpP->numArguments; ++i) {
+            cpP->argumentArray[i] = strdup(argv[getopt_argstart() + i]);
+            if (cpP->argumentArray[i] == NULL) {
+                fprintf(stderr, "Unable to allocate memory for Argument %u\n",
+                        i);
+                abort();
+            }
+        }
+    }
+}
+
+
+
+void
+cmd_processOptions(cmdlineParser   const cpP,
+                   int             const argc,
+                   const char **   const argv, 
+                   const char **   const errorP) {
+
+    struct optionx * longopts;
+
+    longopts = createLongOptsArray(cpP->optionDescArray, cpP->numOptions);
+
+    if (longopts == NULL) 
+        casprintf(errorP, "Unable to get memory for longopts array");
+    else {
+        int endOfOptions;
+        unsigned int i;
+
+        *errorP = NULL;
+
+        /* Set up initial assumption:  No options present */
+
+        for (i = 0; i < cpP->numOptions; ++i)
+            cpP->optionDescArray[i].present = false;
+
+        endOfOptions = false;  /* initial value */
+            
+        while (!endOfOptions && !*errorP) {
+            int const opterr0 = 0;
+                /* Don't let getopt_long_only() print an error message */
+            unsigned int longoptsIndex;
+            const char * unrecognizedOption;
+            const char * optarg;
+            
+            getopt_long_onlyx(argc, (char**) argv, "", longopts, 
+                              &longoptsIndex, opterr0,
+                              &endOfOptions, &optarg, &unrecognizedOption);
+                              
+            if (unrecognizedOption)
+                casprintf(errorP, "Unrecognized option: '%s'", 
+                          unrecognizedOption);
+            else {
+                if (!endOfOptions)
+                    processOption(&cpP->optionDescArray[longoptsIndex], optarg,
+                                  errorP);
+            }
+        }
+        if (!*errorP)
+            extractArguments(cpP, argc, argv);
+
+        free(longopts);
+    }
+}
+
+
+
+cmdlineParser
+cmd_createOptionParser(void) {
+
+    struct cmdlineParserCtl * cpP;
+
+    MALLOCVAR(cpP);
+
+    if (cpP != NULL) {
+        struct optionDesc * optionDescArray;
+
+        cpP->numOptions = 0;
+        MALLOCARRAY(optionDescArray, MAXOPTS);
+        if (optionDescArray == NULL) {
+            free(cpP);
+            cpP = NULL;
+        } else 
+            cpP->optionDescArray = optionDescArray;
+    }
+    return cpP;
+}
+
+
+
+void
+cmd_destroyOptionParser(cmdlineParser const cpP) {
+    
+    unsigned int i;
+
+    for (i = 0; i < cpP->numOptions; ++i) {
+        struct optionDesc const option = cpP->optionDescArray[i];
+        if (option.type == OPTTYPE_STRING && option.present)
+            strfree(option.value.s);
+        strfree(option.name);
+    }
+
+    for (i = 0; i < cpP->numArguments; ++i)
+        strfree(cpP->argumentArray[i]);
+
+    free(cpP->optionDescArray);
+    free(cpP);
+}
+
+
+
+void
+cmd_defineOption(cmdlineParser   const cpP,
+                 const char *    const name, 
+                 enum optiontype const type) {
+    
+    if (cpP->numOptions < MAXOPTS) {
+        cpP->optionDescArray[cpP->numOptions].name = strdup(name);
+        cpP->optionDescArray[cpP->numOptions].type = type;
+        
+        ++cpP->numOptions;
+    }
+}
+
+
+
+static struct optionDesc *
+findOptionDesc(struct cmdlineParserCtl * const cpP,
+               const char *              const name) {
+
+    struct optionDesc * retval;
+    unsigned int i;
+
+    retval = NULL;
+
+    for (i = 0; i < cpP->numOptions && !retval; ++i)
+        if (strcmp(cpP->optionDescArray[i].name, name) == 0)
+            retval = &cpP->optionDescArray[i];
+
+    return retval;
+}
+
+
+
+int
+cmd_optionIsPresent(cmdlineParser const cpP,
+                    const char *  const name) {
+
+    struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
+
+    bool present;
+
+    if (!optionDescP) {
+        fprintf(stderr, "cmdlineParser called incorrectly.  "
+                "optionIsPresent() called for undefined option '%s'\n",
+                name);
+        abort();
+    } else 
+        present = optionDescP->present;
+
+    return present;
+}
+
+
+
+unsigned int
+cmd_getOptionValueUint(cmdlineParser const cpP,
+                       const char *  const name) {
+
+    struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
+
+    unsigned int retval;
+
+    if (!optionDescP) {
+        fprintf(stderr, "cmdlineParser called incorrectly.  "
+                "cmd_getOptionValueUint() called for undefined option '%s'\n",
+                name);
+        abort();
+    } else {
+        if (optionDescP->type != OPTTYPE_UINT) {
+            fprintf(stderr, "cmdlineParser called incorrectly.  "
+                    "cmd_getOptionValueUint() called for non-unsigned integer "
+                    "option '%s'\n", optionDescP->name);
+            abort();
+        } else {
+            if (optionDescP->present) 
+                retval = optionDescP->value.u;
+            else
+                retval = 0;
+        }
+    }
+    return retval;
+}
+
+
+
+int
+cmd_getOptionValueInt(cmdlineParser const cpP,
+                      const char *  const name) {
+
+    struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
+
+    int retval;
+
+    if (!optionDescP) {
+        fprintf(stderr, "cmdlineParser called incorrectly.  "
+                "cmd_getOptionValueInt() called for undefined option '%s'\n",
+                name);
+        abort();
+    } else {
+        if (optionDescP->type != OPTTYPE_INT) {
+            fprintf(stderr, "cmdlineParser called incorrectly.  "
+                    "cmd_getOptionValueInt() called for non-integer "
+                    "option '%s'\n", optionDescP->name);
+            abort();
+        } else {
+            if (optionDescP->present) 
+                retval = optionDescP->value.i;
+            else
+                retval = 0;
+        }
+    }
+
+    return retval;
+}
+
+
+
+const char *
+cmd_getOptionValueString(cmdlineParser const cpP,
+                         const char *  const name) {
+
+    struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
+
+    const char * retval;
+
+    if (!optionDescP) {
+        fprintf(stderr, "cmdlineParser called incorrectly.  "
+                "cmd_getOptionValueString() called for " 
+                "undefined option '%s'\n",
+                name);
+        abort();
+    } else {
+        if (optionDescP->type != OPTTYPE_STRING) {
+            fprintf(stderr, "cmdlineParser called incorrectly.  "
+                    "getOptionValueString() called for non-string "
+                    "option '%s'\n", optionDescP->name);
+            abort();
+        } else {
+            if (optionDescP->present) {
+                retval = strdup(optionDescP->value.s);
+                if (retval == NULL) {
+                    fprintf(stderr, 
+                            "out of memory in cmd_getOptionValueString()\n");
+                    abort();
+                }
+            } else
+                retval = NULL;
+        }
+    }
+    return retval;
+}
+
+
+
+unsigned int 
+cmd_argumentCount(cmdlineParser const cpP) {
+
+    return cpP->numArguments;
+
+}
+                  
+
+
+const char * 
+cmd_getArgument(cmdlineParser const cpP, 
+                unsigned int  const argNumber) { 
+
+    const char * retval;
+    if (argNumber >= cpP->numArguments)
+        retval = NULL;
+    else {
+        retval = strdup(cpP->argumentArray[argNumber]);
+
+        if (retval == NULL) {
+            fprintf(stderr, 
+                    "out of memory in cmd_getArgument()\n");
+            abort();
+        }
+    }
+    return retval;
+}
diff --git a/lib/util/getoptx.c b/lib/util/getoptx.c
new file mode 100644 (file)
index 0000000..6ced36b
--- /dev/null
@@ -0,0 +1,466 @@
+/* This version of `getopt' appears to the caller like standard Unix getopt()
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As getopt() works, it permutes the elements of `argv' so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable _POSIX_OPTION_ORDER disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "getoptx.h"
+
+/* Note that on some systems, the header files above declare variables
+   for use with their native getopt facilities, and those variables have
+   the same names as we'd like to use.  So we use things like optargx
+   instead of optarg to avoid the collision.
+*/
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+*/
+static char *optargx = 0;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to getoptx().
+
+   On entry to getoptx(), zero means this is the first call; initialize.
+
+   When getoptx() returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optindx' communicates from one call to the next
+   how much of ARGV has been scanned so far.  
+*/
+
+static int optindx = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  
+*/
+
+static int opterrx;
+
+/* Index in _GETOPT_LONG_OPTIONS of the long-named option actually found.
+   Only valid when a long-named option was found. */
+
+static int option_index;
+
+struct optionx * _getopt_long_options;
+
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+    which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optindx), which contains all
+    the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+    the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange(char ** const argv) {
+    unsigned int const nonopts_size = 
+        (last_nonopt - first_nonopt) * sizeof (char *);
+    char **temp = (char **) malloc (nonopts_size);
+
+    if (temp == NULL)
+        abort();
+
+    /* Interchange the two blocks of data in argv.  */
+
+    bcopy (&argv[first_nonopt], temp, nonopts_size);
+    bcopy (&argv[last_nonopt], &argv[first_nonopt],
+           (optindx - last_nonopt) * sizeof (char *));
+    bcopy (temp, &argv[first_nonopt + optindx - last_nonopt],
+           nonopts_size);
+
+    /* Update records for the slots the non-options now occupy.  */
+
+    first_nonopt += (optindx - last_nonopt);
+    last_nonopt = optindx;
+
+    free(temp);
+}
+\f
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If getoptx()
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If getoptx() finds another option character, it returns that character,
+   updating `optindx' and `nextchar' so that the next call to getoptx() can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, getoptx() returns `EOF'.
+   Then `optindx' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterrx' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optargx'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optargx', otherwise `optargx' is set to zero.
+
+   If OPTSTRING starts with `-', it requests a different method of handling the
+   non-option ARGV-elements.  See the comments about RETURN_IN_ORDER, above.
+
+   Long-named options begin with `+' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   getoptx() returns 0 when it finds a long-named option.  */
+
+static int
+getoptx(int          const argc, 
+        char **      const argv, 
+        const char * const optstring) {
+
+    optargx = 0;
+
+    /* Initialize the internal data when the first call is made.
+       Start processing options with ARGV-element 1 (since ARGV-element 0
+       is the program name); the sequence of previously skipped
+       non-option ARGV-elements is empty.  */
+
+    if (optindx == 0)
+    {
+        first_nonopt = last_nonopt = optindx = 1;
+
+        nextchar = 0;
+
+    }
+
+    if (nextchar == 0 || *nextchar == 0)
+    {
+        /* If we have just processed some options following some non-options,
+               exchange them so that the options come first.  */
+
+        if (first_nonopt != last_nonopt && last_nonopt != optindx)
+            exchange (argv);
+        else if (last_nonopt != optindx)
+            first_nonopt = optindx;
+
+            /* Now skip any additional non-options
+               and extend the range of non-options previously skipped.  */
+
+        while (optindx < argc
+               && (argv[optindx][0] != '-'|| argv[optindx][1] == 0)
+               && (argv[optindx][0] != '+'|| argv[optindx][1] == 0))
+            optindx++;
+        last_nonopt = optindx;
+
+        /* Special ARGV-element `--' means premature end of options.
+           Skip it like a null option,
+           then exchange with previous non-options as if it were an option,
+           then skip everything else like a non-option.  */
+
+        if (optindx != argc && !strcmp (argv[optindx], "--"))
+        {
+            optindx++;
+
+            if (first_nonopt != last_nonopt && last_nonopt != optindx)
+                exchange (argv);
+            else if (first_nonopt == last_nonopt)
+                first_nonopt = optindx;
+            last_nonopt = argc;
+
+            optindx = argc;
+        }
+
+        /* If we have done all the ARGV-elements, stop the scan
+           and back over any non-options that we skipped and permuted.  */
+
+        if (optindx == argc)
+        {
+            /* Set the next-arg-index to point at the non-options
+               that we previously skipped, so the caller will digest them.  */
+            if (first_nonopt != last_nonopt)
+                optindx = first_nonopt;
+            return EOF;
+        }
+     
+        /* If we have come to a non-option and did not permute it,
+           either stop the scan or describe it to the caller and pass
+           it by.  
+        */
+
+        if ((argv[optindx][0] != '-' || argv[optindx][1] == 0)
+            && (argv[optindx][0] != '+' || argv[optindx][1] == 0))
+        {
+            optargx = argv[optindx++];
+            return 1;
+        }
+
+        /* We have found another option-ARGV-element.
+           Start decoding its characters.  */
+
+        nextchar = argv[optindx] + 1;
+    }
+
+    if ((argv[optindx][0] == '+' || (argv[optindx][0] == '-'))
+        )
+    {
+        struct optionx *p;
+        char *s = nextchar;
+        int exact = 0;
+        int ambig = 0;
+        struct optionx * pfound;
+        int indfound;
+
+        while (*s && *s != '=') s++;
+
+        indfound = 0;  /* quite compiler warning */
+
+        /* Test all options for either exact match or abbreviated matches.  */
+        for (p = _getopt_long_options, option_index = 0, pfound = NULL;
+             p->name; 
+             p++, option_index++)
+            if (!strncmp (p->name, nextchar, s - nextchar))
+            {
+                if ((unsigned int)(s - nextchar) == strlen (p->name))
+                {
+                    /* Exact match found.  */
+                    pfound = p;
+                    indfound = option_index;
+                    exact = 1;
+                    break;
+                }
+                else if (!pfound)
+                {
+                    /* First nonexact match found.  */
+                    pfound = p;
+                    indfound = option_index;
+                }
+                else
+                    /* Second nonexact match found.  */
+                    ambig = 1;
+            }
+
+        if (ambig && !exact)
+        {
+            fprintf (stderr, "%s: option `%s' is ambiguous\n",
+                     argv[0], argv[optindx]);
+            nextchar += strlen (nextchar);               
+            return '?';
+        }
+
+        if (pfound)
+        {
+            option_index = indfound;
+            optindx++;
+            if (*s)
+            {
+                if (pfound->has_arg > 0)
+                    optargx = s + 1;
+                else
+                {
+                    fprintf (stderr,
+                             "%s: option `%c%s' doesn't allow an argument\n",
+                             argv[0], argv[optindx - 1][0], pfound->name);
+                    nextchar += strlen (nextchar);               
+                    return '?';
+                }
+            }
+            else if (pfound->has_arg)
+            {
+                if (optindx < argc)
+                    optargx = argv[optindx++];
+                else if (pfound->has_arg != 2)
+                {
+                    fprintf (stderr, "%s: option `%s' requires an argument\n",
+                             argv[0], argv[optindx - 1]);
+                    nextchar += strlen (nextchar);           
+                    return '?';
+                }
+            }
+            nextchar += strlen (nextchar);
+            if (pfound->flag)
+                *(pfound->flag) = pfound->val;
+            return 0;
+        }
+        if (argv[optindx][0] == '+' || index (optstring, *nextchar) == 0)
+        {
+            if (opterrx != 0)
+                fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+                         argv[0], argv[optindx][0], nextchar);
+            nextchar += strlen (nextchar);           
+            return '?';
+        }
+    }
+    /* Look at and handle the next option-character.  */
+
+    {
+        char c = *nextchar++;
+        char *temp = index (optstring, c);
+
+        /* Increment `optindx' when we start to process its last character.  */
+        if (*nextchar == 0)
+            optindx++;
+
+        if (temp == 0 || c == ':')
+        {
+            if (opterrx != 0)
+            {
+                if (c < 040 || c >= 0177)
+                    fprintf (stderr, "%s: unrecognized option, "
+                             "character code 0%o\n",
+                             argv[0], c);
+                else
+                    fprintf (stderr, "%s: unrecognized option `-%c'\n",
+                             argv[0], c);
+            }
+            return '?';
+        }
+        if (temp[1] == ':')
+        {
+            if (temp[2] == ':')
+            {
+                /* This is an option that accepts an argument optionally.  */
+                if (*nextchar != 0)
+                {
+                    optargx = nextchar;
+                    optindx++;
+                }
+                else
+                    optargx = 0;
+                nextchar = 0;
+            }
+            else
+            {
+                /* This is an option that requires an argument.  */
+                if (*nextchar != 0)
+                {
+                    optargx = nextchar;
+                    /* If we end this ARGV-element by taking the rest
+                       as an arg, we must advance to the next element
+                       now.  
+                    */
+                    optindx++;
+                }
+                else if (optindx == argc)
+                {
+                    if (opterrx != 0)
+                        fprintf (stderr,
+                                 "%s: option `-%c' requires an argument\n",
+                                 argv[0], c);
+                    c = '?';
+                }
+                else
+                    /* We already incremented `optindx' once;
+                       increment it again when taking next ARGV-elt as
+                       argument.
+                    */
+                    optargx = argv[optindx++];
+                nextchar = 0;
+            }
+        }
+        return c;
+    }
+}
+
+
+
+void
+getopt_long_onlyx(int              const argc, 
+                  char **          const argv, 
+                  const char *     const options, 
+                  struct optionx * const long_options, 
+                  unsigned int *   const opt_index, 
+                  int              const opterrArg,
+                  int *            const end_of_options,
+                  const char **    const optarg_arg,
+                  const char **    const unrecognized_option) {
+
+    int rc;
+
+    opterrx = opterrArg;
+    _getopt_long_options = long_options;
+    rc = getoptx(argc, argv, options);
+    if (rc == 0)
+        *opt_index = option_index;
+
+    if (rc == '?')
+        *unrecognized_option = argv[optindx];
+    else
+        *unrecognized_option = NULL;
+
+    if (rc < 0)
+        *end_of_options = 1;
+    else
+        *end_of_options = 0;
+
+    *optarg_arg = optargx;
+}
+     
+
+unsigned int
+getopt_argstart(void) {
+/*----------------------------------------------------------------------------
+   This is a replacement for what traditional getopt does with global
+   variables.
+
+   You call this after getopt_long_onlyx() has returned "end of
+   options"
+-----------------------------------------------------------------------------*/
+    return optindx;
+}
+
+
+/* Getopt for GNU.
+   Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
diff --git a/lib/util/getoptx.h b/lib/util/getoptx.h
new file mode 100644 (file)
index 0000000..c688331
--- /dev/null
@@ -0,0 +1,51 @@
+/* Interface to getopt_long_onlyx() */
+
+
+enum argreq {no_argument, required_argument, optional_argument};
+
+struct optionx {
+    /* This describes an option.  If the field `flag' is nonzero, it
+       points to a variable that is to be set to the value given in
+       the field `val' when the option is found, but left unchanged if
+       the option is not found.  
+    */
+    const char * name;
+    enum argreq has_arg;
+    int * flag;
+    int val;
+};
+
+/* long_options[] is a list terminated by an element that contains
+   a NULL 'name' member.
+*/
+void
+getopt_long_onlyx(int              const argc, 
+                  char **          const argv, 
+                  const char *     const options, 
+                  struct optionx * const long_options, 
+                  unsigned int *   const opt_index, 
+                  int              const opterrArg,
+                  int *            const end_of_options,
+                  const char **    const optarg_arg,
+                  const char **    const unrecognized_option);
+
+unsigned int
+getopt_argstart(void);
+
+/* 
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
diff --git a/lib/util/include/bool.h b/lib/util/include/bool.h
new file mode 100644 (file)
index 0000000..312477c
--- /dev/null
@@ -0,0 +1,18 @@
+/* This takes the place of C99 stdbool.h, which at least some Windows
+   compilers don't have.  (October 2005).
+
+   One must not also include <stdbool.h>, because it might cause a name
+   collision.
+*/
+
+#ifndef __cplusplus
+/* At least the GNU compiler defines __bool_true_false_are_defined */
+#ifndef __bool_true_false_are_defined
+#define __bool_true_false_are_defined
+typedef enum {
+    false = 0,
+    true = 1
+} bool;
+#endif
+#endif
+
diff --git a/lib/util/include/c_util.h b/lib/util/include/c_util.h
new file mode 100644 (file)
index 0000000..da078e8
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef C_UTIL_H_INCLUDED
+#define C_UTIL_H_INCLUDED
+
+/* C language stuff.  Doesn't involve any libraries that aren't part of
+   the compiler.
+*/
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type
+   calls to be sure the arguments match the format string, thus preventing
+   runtime segmentation faults and incorrect messages.
+*/
+#ifdef __GNUC__
+#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
+#else
+#define GNU_PRINTF_ATTR(a,b)
+#endif
+
+#endif
diff --git a/lib/util/include/casprintf.h b/lib/util/include/casprintf.h
new file mode 100644 (file)
index 0000000..a5d0e4a
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef CASPRINTF_H_INCLUDED
+#define CASPRINTF_H_INCLUDED
+
+#include <stdarg.h>
+
+#include "c_util.h"
+
+extern const char * const strsol;
+
+void
+cvasprintf(const char ** const retvalP,
+           const char *  const fmt,
+           va_list             varargs);
+
+void GNU_PRINTF_ATTR(2,3)
+casprintf(const char ** const retvalP, const char * const fmt, ...);
+
+void
+strfree(const char * const string);
+
+#endif
diff --git a/lib/util/include/cmdline_parser.h b/lib/util/include/cmdline_parser.h
new file mode 100644 (file)
index 0000000..ce42506
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef CMDLINE_PARSER_H
+#define CMDLINE_PARSER_H
+
+
+/*
+
+   NOTE NOTE NOTE: cmd_getOptionValueString() and
+   cmd_getArgument() return malloc'ed memory (and abort the program if
+   out of memory).  You must free it.
+
+*/
+
+enum optiontype {OPTTYPE_FLAG, OPTTYPE_INT, OPTTYPE_UINT, OPTTYPE_STRING};
+
+struct cmdlineParserCtl;
+
+typedef struct cmdlineParserCtl * cmdlineParser;
+
+void
+cmd_processOptions(cmdlineParser   const cpP,
+                   int             const argc,
+                   const char **   const argv, 
+                   const char **   const errorP);
+
+cmdlineParser
+cmd_createOptionParser(void);
+
+void
+cmd_destroyOptionParser(cmdlineParser const cpP);
+
+void
+cmd_defineOption(cmdlineParser   const cpP,
+                 const char *    const name, 
+                 enum optiontype const type);
+    
+int
+cmd_optionIsPresent(cmdlineParser const cpP,
+                    const char *  const name);
+
+unsigned int
+cmd_getOptionValueUint(cmdlineParser const cpP,
+                       const char *  const name);
+
+int
+cmd_getOptionValueInt(cmdlineParser const cpP,
+                      const char *  const name);
+
+const char *
+cmd_getOptionValueString(cmdlineParser const cpP,
+                         const char *  const name);
+
+unsigned int 
+cmd_argumentCount(cmdlineParser const cpP);
+
+const char * 
+cmd_getArgument(cmdlineParser const cpP, 
+                unsigned int  const argNumber); 
+
+#endif
diff --git a/lib/util/include/girmath.h b/lib/util/include/girmath.h
new file mode 100644 (file)
index 0000000..0ced9c8
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __GIRMATH_H
+#define __GIRMATH_H
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+#endif
+
diff --git a/lib/util/include/girstring.h b/lib/util/include/girstring.h
new file mode 100644 (file)
index 0000000..f2cdc81
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef GIRSTRING_H_INCLUDED
+#define GIRSTRING_H_INCLUDED
+
+#include <string.h>
+#include "bool.h"
+
+char
+stripeq(const char * const comparand, const char * const comparator);
+
+char
+stripcaseeq(const char * const comparand, const char * const comparator);
+
+void
+stripcpy(char * dest, const char * source);
+
+void
+stripcasecpy(char * dest, const char * source);
+
+char *
+stripdup(const char * const input);
+
+char *
+strcasedup(const char input[]);
+
+static __inline__ bool
+streq(const char * const comparator,
+      const char * const comparand) {
+
+    return (strcmp(comparand, comparator) == 0);
+}
+
+static __inline__ const char *
+sdup(const char * const input) {
+    return (const char *) strdup(input);
+}
+
+/* Copy string pointed by B to array A with size checking.  */
+#define SSTRCPY(A,B) \
+       (strncpy((A), (B), sizeof(A)), *((A)+sizeof(A)-1) = '\0')
+#define SSTRCMP(A,B) \
+       (strncmp((A), (B), sizeof(A)))
+
+/* Concatenate string B onto string in array A with size checking */
+#define STRSCAT(A,B) \
+    (strncat((A), (B), sizeof(A)-strlen(A)), *((A)+sizeof(A)-1) = '\0')
+
+#endif
diff --git a/lib/util/include/inline.h b/lib/util/include/inline.h
new file mode 100644 (file)
index 0000000..f90032b
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef XMLRPC_INLINE_H_INCLUDED
+#define XMLRPC_INLINE_H_INCLUDED
+
+/* Xmlrpc-c uses __inline__ to declare functions that should be
+    compiled as inline code.  Some compilers, e.g. GNU, recognize the
+    __inline__ keyword.
+*/
+#ifndef __GNUC__
+#ifndef __inline__
+#ifdef __sgi
+#define __inline__ __inline
+#else
+#define __inline__
+#endif
+#endif
+#endif
+
+
+#endif
diff --git a/lib/util/include/linklist.h b/lib/util/include/linklist.h
new file mode 100644 (file)
index 0000000..f6f2641
--- /dev/null
@@ -0,0 +1,193 @@
+#ifndef LINKLIST_H_INCLUDED
+#define LINKLIST_H_INCLUDED
+
+#include "inline.h"
+
+struct list_head {
+/*----------------------------------------------------------------------------
+  This is a header for an element of a doubly linked list, or an anchor
+  for such a list.
+
+  itemP == NULL means it's an anchor; otherwise it's a header.
+
+  Initialize a list header with list_init_header().  You don't have to
+  do anything to terminate a list header.
+
+  Initialize an anchor with list_make_emtpy().  You don't have to do anything
+  to terminate a list header.
+-----------------------------------------------------------------------------*/
+    struct list_head * nextP;
+        /* For a header, this is the address of the list header for
+           the next element in the list.  If there is no next element,
+           it points to the anchor.  If the header is not in a list at
+           all, it is NULL.
+
+           For an anchor, it is the address of the list header of the
+           first element.  If the list is empty, it points to the
+           anchor itself.  
+        */
+    struct list_head * prevP;
+        /* For a header, this is the address of the list header for
+           the previous element in the list.  If there is no previous element,
+           it points to the anchor.  If the header is not in a list at
+           all, it is NULL.
+
+           For an anchor, it is the address of the list header of the
+           last element.  If the list is empty, it points to the
+           anchor itself.  
+        */
+    void * itemP;
+        /* For a header, this is the address of the list element to which it
+           belongs.  For an anchor, this is NULL.
+        */
+};
+
+static __inline__ void
+list_init_header(struct list_head * const headerP,
+                 void *             const itemP) {
+
+    headerP->prevP = NULL;
+    headerP->nextP = NULL;
+    headerP->itemP = itemP;
+}
+
+
+
+static __inline__ int
+list_is_linked(struct list_head * headerP) {
+    return headerP->prevP != NULL;
+}
+
+
+
+static __inline__ int
+list_is_empty(struct list_head * const anchorP)  {
+    return anchorP->nextP == anchorP;
+}
+
+
+
+static __inline__ unsigned int
+list_count(struct list_head * const anchorP) {
+    unsigned int count;
+
+    struct list_head * p;
+
+    for (p = anchorP->nextP, count = 0;
+         p != anchorP;
+         p = p->nextP, ++count);
+
+    return count;
+}
+
+
+
+static __inline__ void
+list_make_empty(struct list_head * const anchorP) {
+    anchorP->prevP = anchorP;
+    anchorP->nextP = anchorP;
+    anchorP->itemP = NULL;
+}
+
+static __inline__ void
+list_insert_after(struct list_head * const beforeHeaderP,
+                  struct list_head * const newHeaderP) {
+    newHeaderP->prevP = beforeHeaderP;
+    newHeaderP->nextP = beforeHeaderP->nextP;
+
+    beforeHeaderP->nextP = newHeaderP;
+    newHeaderP->nextP->prevP = newHeaderP;
+}
+
+
+
+static __inline__ void
+list_add_tail(struct list_head * const anchorP,
+              struct list_head * const headerP) {
+    list_insert_after(anchorP->prevP, headerP);
+}
+
+
+
+static __inline__ void
+list_add_head(struct list_head * const anchorP,
+              struct list_head * const headerP) {
+    list_insert_after(anchorP, headerP);
+}
+
+
+
+static __inline__ void
+list_remove(struct list_head * const headerP) {
+    headerP->prevP->nextP = headerP->nextP;
+    headerP->nextP->prevP = headerP->prevP;
+    headerP->prevP = NULL;
+    headerP->nextP = NULL;
+}
+
+
+
+static __inline__ struct list_head *
+list_remove_head(struct list_head * const anchorP) {
+    struct list_head * retval;
+
+    if (list_is_empty(anchorP))
+        retval = NULL;
+    else {
+        retval = anchorP->nextP;
+        list_remove(retval);
+    }            
+    return retval;
+}
+
+
+
+static __inline__ struct list_head *
+list_remove_tail(struct list_head * const anchorP) {
+    struct list_head * retval;
+
+    if (list_is_empty(anchorP))
+        retval = NULL;
+    else {
+        retval = anchorP->prevP;
+        list_remove(retval);
+    }            
+    return retval;
+}
+
+
+
+static __inline__ void *
+list_foreach(struct list_head * const anchorP,
+             void * functionP(struct list_head *, void *),
+             void *             const context) {
+
+    struct list_head * p;
+    struct list_head * nextP;
+    void * result;
+
+    for (p = anchorP->nextP, nextP = p->nextP, result=NULL;
+         p != anchorP && result == NULL; 
+         p = nextP, nextP = p->nextP) 
+        result = (*functionP)(p, context);
+
+    return result;
+}
+
+
+
+static __inline__ void
+list_append(struct list_head * const newAnchorP,
+            struct list_head * const baseAnchorP) {
+
+    if (!list_is_empty(newAnchorP)) {
+        baseAnchorP->prevP->nextP = newAnchorP->nextP;
+        newAnchorP->nextP->prevP = baseAnchorP->prevP;
+        newAnchorP->prevP->nextP = baseAnchorP;
+        baseAnchorP->prevP = newAnchorP->prevP;
+    }
+}
+
+#endif
+
+
diff --git a/lib/util/include/mallocvar.h b/lib/util/include/mallocvar.h
new file mode 100644 (file)
index 0000000..9c4f994
--- /dev/null
@@ -0,0 +1,100 @@
+/* These are some dynamic memory allocation facilities.  They are essentially
+   an extension to C, as they do allocations with a cognizance of C 
+   variables.  You can use them to make C read more like a high level
+   language.
+
+   Before including this, you must define an __inline__ macro if your
+   compiler doesn't recognize it as a keyword.
+*/
+
+#ifndef MALLOCVAR_INCLUDED
+#define MALLOCVAR_INCLUDED
+
+#include "xmlrpc_config.h"
+
+#include <limits.h>
+#include <stdlib.h>
+
+static __inline__ void
+mallocProduct(void **      const resultP, 
+              unsigned int const factor1,
+              unsigned int const factor2) {
+/*----------------------------------------------------------------------------
+   malloc a space whose size in bytes is the product of 'factor1' and
+   'factor2'.  But if that size cannot be represented as an unsigned int,
+   return NULL without allocating anything.  Also return NULL if the malloc
+   fails.
+
+   If either factor is zero, malloc a single byte.
+
+   Note that malloc() actually takes a size_t size argument, so the
+   proper test would be whether the size can be represented by size_t,
+   not unsigned int.  But there is no reliable indication available to
+   us, like UINT_MAX, of what the limitations of size_t are.  We
+   assume size_t is at least as expressive as unsigned int and that
+   nobody really needs to allocate more than 4GB of memory.
+-----------------------------------------------------------------------------*/
+    if (factor1 == 0 || factor2 == 0)
+        *resultP = malloc(1);
+    else {
+        if (UINT_MAX / factor2 < factor1) 
+            *resultP = NULL;
+        else 
+            *resultP = malloc(factor1 * factor2); 
+    }
+}
+
+
+
+static __inline__ void
+reallocProduct(void **      const blockP,
+               unsigned int const factor1,
+               unsigned int const factor2) {
+    
+    if (UINT_MAX / factor2 < factor1) 
+        *blockP = NULL;
+    else 
+        *blockP = realloc(*blockP, factor1 * factor2); 
+}
+
+
+/* IMPLEMENTATION NOTE:  There are huge strict aliasing pitfalls here
+   if you cast pointers, e.g. (void **)
+*/
+
+#define MALLOCARRAY(arrayName, nElements) do { \
+    void * array; \
+    mallocProduct(&array, nElements, sizeof(arrayName[0])); \
+    arrayName = array; \
+} while (0)
+
+#define REALLOCARRAY(arrayName, nElements) { \
+    void * array = arrayName; \
+    reallocProduct(&array, nElements, sizeof(arrayName[0])); \
+    arrayName = array; \
+} while (0)
+
+
+#define MALLOCARRAY_NOFAIL(arrayName, nElements) \
+do { \
+    MALLOCARRAY(arrayName, nElements); \
+    if ((arrayName) == NULL) \
+        abort(); \
+} while(0)
+
+#define REALLOCARRAY_NOFAIL(arrayName, nElements) \
+do { \
+    REALLOCARRAY(arrayName, nElements); \
+    if ((arrayName) == NULL) \
+        abort(); \
+} while(0)
+
+
+#define MALLOCVAR(varName) \
+    varName = malloc(sizeof(*varName))
+
+#define MALLOCVAR_NOFAIL(varName) \
+    do {if ((varName = malloc(sizeof(*varName))) == NULL) abort();} while(0)
+
+#endif
+
diff --git a/lib/util/include/pthreadx.h b/lib/util/include/pthreadx.h
new file mode 100644 (file)
index 0000000..dcdb411
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#ifndef PTHREADX_H_INCLUDED
+#define PTHREADX_H_INCLUDED
+
+#ifndef WIN32
+#  define _REENTRANT
+#  include <pthread.h>
+#elif defined (WIN32)
+
+typedef HANDLE pthread_t;
+typedef CRITICAL_SECTION pthread_mutex_t;
+
+#define PTHREAD_MUTEX_INITIALIZER NULL
+    //usage: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+typedef
+struct {
+    int attrs; //currently unused. placeholder.
+} pthread_attr_t;
+
+typedef
+struct {
+    int attrs; //currently unused. placeholder.
+} pthread_mutexattr_t;
+
+//typedef void * (*pthread_func)(void *);
+typedef unsigned ( __stdcall *pthread_func )( void * );
+
+extern int pthread_create(pthread_t *new_thread_ID,
+                          const pthread_attr_t *attr,
+                          pthread_func start_func, void *arg);
+extern int pthread_cancel(pthread_t target_thread);
+extern int pthread_join(pthread_t target_thread, void **status);
+extern int pthread_detach(pthread_t target_thread);
+
+extern int pthread_mutex_init(pthread_mutex_t *mp,
+                              const pthread_mutexattr_t *attr);
+extern int pthread_mutex_lock(pthread_mutex_t *mp);
+extern int pthread_mutex_unlock(pthread_mutex_t *mp);
+extern int pthread_mutex_destroy(pthread_mutex_t *mp);
+
+#endif  /* WIN32 */
+
+#endif
diff --git a/lib/util/include/unistdx.h b/lib/util/include/unistdx.h
new file mode 100644 (file)
index 0000000..69f1f6b
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef UNISTDX_H_INCLUDED
+#define UNISTDX_H_INCLUDED
+
+/* Xmlrpc-c code #includes "unistdx.h" instead of <unistd.h> because
+   <unistd.h> does not exist on WIN32.
+*/
+
+#ifndef WIN32
+#  include <unistd.h>
+#else
+
+#endif  /* WIN32 */
+
+#endif
diff --git a/lib/util/pthreadx_win32.c b/lib/util/pthreadx_win32.c
new file mode 100644 (file)
index 0000000..a295fb0
--- /dev/null
@@ -0,0 +1,101 @@
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#include "xmlrpc_config.h"
+
+#if WIN32
+
+#include "pthreadx.h"
+
+#include <process.h>
+
+#undef PACKAGE
+#undef VERSION
+
+int pthread_create(pthread_t *new_thread_ID,
+                   const pthread_attr_t * attr,
+                   pthread_func start_func, void *arg)
+{
+    HANDLE hThread;
+    DWORD dwThreadID;
+
+    hThread = (HANDLE) _beginthreadex (
+        NULL, 0, start_func, (LPVOID)arg, CREATE_SUSPENDED, &dwThreadID);
+
+    SetThreadPriority (hThread, THREAD_PRIORITY_NORMAL); 
+    ResumeThread (hThread);
+
+    *new_thread_ID = hThread;
+
+    return hThread ? 0 : -1;
+}
+
+/* Just kill it. */
+int pthread_cancel(pthread_t target_thread)
+{
+    CloseHandle (target_thread);
+    return 0;
+}
+
+/* Waits for the thread to exit before continuing. */
+int pthread_join(pthread_t target_thread, void **status)
+{
+    DWORD dwResult = WaitForSingleObject(target_thread, INFINITE);
+    (*status) = (void *)dwResult;
+    return 0;
+}
+
+/* Stubbed. Do nothing. */
+int pthread_detach(pthread_t target_thread)
+{
+    return 0;
+}
+
+int pthread_mutex_init(pthread_mutex_t *mp,
+                       const pthread_mutexattr_t * attr)
+{
+    InitializeCriticalSection(mp);
+    return 0;
+}
+
+int pthread_mutex_lock(pthread_mutex_t *mp)
+{
+    EnterCriticalSection(mp);
+    return 0;
+}
+
+int pthread_mutex_unlock(pthread_mutex_t *mp)
+{
+    LeaveCriticalSection(mp);
+    return 0;
+}
+
+int pthread_mutex_destroy(pthread_mutex_t *mp)
+{
+    DeleteCriticalSection(mp);
+    return 0;
+}
+
+#endif
diff --git a/lib/wininet_transport/Makefile b/lib/wininet_transport/Makefile
new file mode 100644 (file)
index 0000000..cf0c52d
--- /dev/null
@@ -0,0 +1,40 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+
+include $(SRCDIR)/Makefile.config
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+LDFLAGS = -lpthread $(LADD)
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/src
+
+default: all
+
+.PHONY: all
+all: xmlrpc_wininet_transport.lo
+
+.PHONY: clean
+clean: clean-common
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: tags
+tags: TAGS
+
+.PHONY: distdir
+distdir:
+
+.PHONY: install
+install:
+
+.PHONY: dep
+dep: dep-common
+
+include $(SRCDIR)/Makefile.common
+
+include Makefile.depend
+
+xmlrpc_wininet_transport.lo:%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
diff --git a/lib/wininet_transport/xmlrpc_wininet_transport.c b/lib/wininet_transport/xmlrpc_wininet_transport.c
new file mode 100644 (file)
index 0000000..c583309
--- /dev/null
@@ -0,0 +1,919 @@
+/*=============================================================================
+                           xmlrpc_wininet_transport
+===============================================================================
+   WinInet-based client transport for Xmlrpc-c.  Copyright information at
+   the bottom of this file.
+   
+   Changelog (changes by Steven A. Bone - sbone@pobox.com unless otherwise noted):
+   05.01.01 - Significant refactoring of the transport layer due to internal
+              changes of the xmlrpc-c transports.  Modeled after the CURL
+              based transport changes by Bryan Henderson.              
+   05.02.03 - Fixed Authorization header - thanks yamer.
+   05.03.20 - Supports xmlrpc_xportparms, xmlrpc_wininet_xportparms added
+              *potential breaking change* - now by default we fail on invalid
+                         SSL certs, use the xmlrpc_wininet_xportparms option to enable old
+                         behavior.
+   
+=============================================================================*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+
+#include "xmlrpc_config.h"
+
+#include "bool.h"
+#include "mallocvar.h"
+#include "linklist.h"
+#include "casprintf.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/client_int.h"
+#include "pthreadx.h"
+
+#if defined (WIN32)
+#      include <wininet.h>
+#endif /*WIN32*/
+
+#if defined (WIN32) && defined(_DEBUG)
+#              include <crtdbg.h>
+#              define new DEBUG_NEW
+#              define malloc(size) _malloc_dbg( size, _NORMAL_BLOCK, __FILE__, __LINE__)
+#              undef THIS_FILE
+               static char THIS_FILE[] = __FILE__;
+#endif /*WIN32 && _DEBUG*/
+
+
+static HINTERNET hSyncInternetSession = NULL;
+
+/* Declare WinInet status callback. */
+void CALLBACK statusCallback (HINTERNET hInternet,
+                          unsigned long dwContext,
+                          unsigned long dwInternetStatus,
+                          void * lpvStatusInformation,
+                          unsigned long dwStatusInformationLength);
+
+
+struct xmlrpc_client_transport {
+    pthread_mutex_t listLock;
+    struct list_head rpcList;
+        /* List of all RPCs that exist for this transport.  An RPC exists
+           from the time the user requests it until the time the user 
+           acknowledges it is done.
+        */
+    int allowInvalidSSLCerts;
+        /* Flag to specify if we ignore invalid SSL Certificates.  If this
+                  is set to zero, calling a XMLRPC server with an invalid SSL
+                  certificate will fail.  This is the default behavior of the other
+                  transports, but invalid certificates were allowed in pre 1.2 
+                  wininet xmlrpc-c transports.
+        */
+};
+
+typedef struct {
+    unsigned long http_status;
+       HINTERNET hHttpRequest;
+       HINTERNET hURL;
+       INTERNET_PORT nPort;
+       char szHostName[255];   
+       char szUrlPath[255];
+       BOOL bUseSSL;
+       char *headerList;
+       BYTE *pSendData;
+       xmlrpc_mem_block *pResponseData;
+} winInetTransaction;
+
+typedef struct {
+    struct list_head link;  /* link in transport's list of RPCs */
+    winInetTransaction * winInetTransactionP;
+        /* The object which does the HTTP transaction, with no knowledge
+           of XML-RPC or Xmlrpc-c.
+        */
+    xmlrpc_mem_block * responseXmlP;
+    xmlrpc_bool threadExists;
+    pthread_t thread;
+    xmlrpc_transport_asynch_complete complete;
+        /* Routine to call to complete the RPC after it is complete HTTP-wise.
+           NULL if none.
+        */
+    struct xmlrpc_call_info * callInfoP;
+        /* User's identifier for this RPC */
+       struct xmlrpc_client_transport * clientTransportP;
+} rpc;
+
+static void
+createWinInetHeaderList( xmlrpc_env *         const envP,
+                                                const xmlrpc_server_info * const serverP,
+                                                char ** const headerListP) {
+
+    char *szHeaderList = NULL;
+       char *szContentType = "Content-Type: text/xml\r\n";
+
+    /* Send an authorization header if we need one. */
+    if (serverP->_http_basic_auth) {
+        /* Make the header with content type and authorization   */
+        /* NOTE: A newline is required between each added header */
+               szHeaderList = malloc(strlen(szContentType) + 17 + strlen(serverP->_http_basic_auth) + 1 );
+        
+        if (szHeaderList == NULL)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR,
+                "Couldn't allocate memory for authorization header");
+        else {
+            memcpy(szHeaderList,szContentType, strlen(szContentType));
+                       memcpy(szHeaderList + strlen(szContentType),"\r\nAuthorization: ", 17);
+                       memcpy(szHeaderList + strlen(szContentType) + 17, serverP->_http_basic_auth,
+                   strlen(serverP->_http_basic_auth) + 1);
+        }
+    }
+       else
+       {
+               /* Just the content type header is needed */
+               szHeaderList = malloc(strlen(szContentType) + 1);
+        
+        if (szHeaderList == NULL)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR, "Couldn't allocate memory for standard header");
+        else 
+            memcpy(szHeaderList,szContentType, strlen(szContentType)+1);
+       }
+
+    *headerListP = szHeaderList;
+}
+
+static void
+createWinInetTransaction(xmlrpc_env *         const envP,
+                      const xmlrpc_server_info * const serverP,
+                      xmlrpc_mem_block *   const callXmlP,
+                      xmlrpc_mem_block *   const responseXmlP,
+                      winInetTransaction **   const winInetTransactionPP) {
+
+    winInetTransaction * winInetTransactionP;
+
+    MALLOCVAR(winInetTransactionP);
+    if (winInetTransactionP == NULL)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "No memory to create WinInet transaction.");
+    else {
+               char szExtraInfo[255];
+               char szScheme[100];
+               URL_COMPONENTS uc;
+
+               /* Init to defaults */
+               winInetTransactionP->http_status = 0;
+               winInetTransactionP->hHttpRequest = NULL;
+               winInetTransactionP->hURL = NULL;
+               winInetTransactionP->headerList=NULL;
+               winInetTransactionP->pSendData=NULL;
+               winInetTransactionP->pResponseData=responseXmlP;
+
+               /* Parse the URL and store results into the  winInetTransaction struct */
+               memset (&uc, 0, sizeof (uc));
+               uc.dwStructSize = sizeof (uc);
+               uc.lpszScheme = szScheme;
+               uc.dwSchemeLength = 100;
+               uc.lpszHostName = winInetTransactionP->szHostName;
+               uc.dwHostNameLength = 255;
+               uc.lpszUrlPath = winInetTransactionP->szUrlPath;
+               uc.dwUrlPathLength = 255;
+               uc.lpszExtraInfo = szExtraInfo;
+               uc.dwExtraInfoLength = 255;
+               if (InternetCrackUrl (serverP->_server_url, strlen (serverP->_server_url), ICU_ESCAPE, &uc) == FALSE)
+               {
+                       xmlrpc_env_set_fault_formatted( envP, XMLRPC_INTERNAL_ERROR,
+                                                                                       "Unable to parse the server URL.");
+               }
+               else
+               {
+                       winInetTransactionP->nPort = (uc.nPort) ? uc.nPort : INTERNET_DEFAULT_HTTP_PORT;
+                       if (_strnicmp (uc.lpszScheme, "https", 5) == 0)
+                               winInetTransactionP->bUseSSL=TRUE;
+                       else
+                               winInetTransactionP->bUseSSL=FALSE;
+                       createWinInetHeaderList(envP, serverP, &winInetTransactionP->headerList);
+
+                       XMLRPC_MEMBLOCK_APPEND(char, envP, callXmlP, "\0", 1);
+                       if (!envP->fault_occurred) {
+                               winInetTransactionP->pSendData = XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP);
+                       }
+               }
+                       
+               
+               if (envP->fault_occurred)
+            free(winInetTransactionP);
+    }
+    *winInetTransactionPP = winInetTransactionP;
+}
+
+
+
+static void
+destroyWinInetTransaction(winInetTransaction * const winInetTransactionP) {
+
+       XMLRPC_ASSERT_PTR_OK(winInetTransactionP);
+
+       if (winInetTransactionP->hHttpRequest)
+               InternetCloseHandle (winInetTransactionP->hHttpRequest);
+
+       if (winInetTransactionP->hURL)
+               InternetCloseHandle (winInetTransactionP->hURL);
+
+       if (winInetTransactionP->headerList)
+               free(winInetTransactionP->headerList);
+
+       free(winInetTransactionP);
+}
+
+static void get_wininet_response (     xmlrpc_env *      const envP,
+                                                                       winInetTransaction * const winInetTransactionP)
+{
+       INTERNET_BUFFERS inetBuffer;
+       LPTSTR pMsg = NULL;
+       PVOID pMsgMem = NULL;
+       unsigned long dwFlags;
+       unsigned long dwErr = 0; 
+       unsigned long nExpected = 0;
+       unsigned long dwLen = sizeof (unsigned long);
+       void * body = NULL;
+       BOOL bOK = FALSE;
+
+       inetBuffer.dwStructSize = sizeof (INTERNET_BUFFERS);
+       inetBuffer.Next = NULL;
+       inetBuffer.lpcszHeader = NULL;
+       inetBuffer.dwHeadersTotal = inetBuffer.dwHeadersLength = 0;
+       inetBuffer.dwOffsetHigh = inetBuffer.dwOffsetLow = 0;
+       inetBuffer.dwBufferLength = 0;
+
+       bOK = HttpQueryInfo (winInetTransactionP->hHttpRequest, 
+               HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, 
+               &inetBuffer.dwBufferTotal, &dwLen, NULL);
+       if (!bOK)
+       {
+               dwErr = GetLastError ();
+               FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+                       FORMAT_MESSAGE_FROM_SYSTEM, 
+                       NULL,
+                       dwErr,
+                       MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                       (LPTSTR) &pMsgMem,
+                       1024,NULL);
+
+               pMsg = (pMsgMem) ? (LPTSTR)(pMsgMem) : "Sync HttpQueryInfo failed.";
+               XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, pMsg);
+       }
+
+    if (inetBuffer.dwBufferTotal == 0)
+               XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, "WinInet returned no data");
+
+       body = inetBuffer.lpvBuffer = calloc (inetBuffer.dwBufferTotal, sizeof (TCHAR));
+       dwFlags = IRF_SYNC;
+       inetBuffer.dwBufferLength = nExpected = inetBuffer.dwBufferTotal;
+       InternetQueryDataAvailable (winInetTransactionP->hHttpRequest, &inetBuffer.dwBufferLength, 0, 0);
+
+       /* Read Response from InternetFile */
+       do
+       {
+               if (inetBuffer.dwBufferLength != 0)
+                       bOK = InternetReadFileEx (winInetTransactionP->hHttpRequest, &inetBuffer, dwFlags, 1);
+
+               if (!bOK)
+                       dwErr = GetLastError ();
+
+               if (dwErr)
+               {
+                       if (dwErr == WSAEWOULDBLOCK || dwErr == ERROR_IO_PENDING) 
+                       {
+                               /* Non-block socket operation wait 10 msecs */
+                               SleepEx (10, TRUE);
+                               /* Reset dwErr to zero for next pass */
+                               dwErr = 0;
+                       }
+                       else
+                       {
+                               FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+                                       FORMAT_MESSAGE_FROM_SYSTEM, 
+                                       NULL,
+                                       dwErr,
+                                       MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                                       (LPTSTR) &pMsgMem,
+                                       1024,NULL);
+                               pMsg = (pMsgMem) ? (LPTSTR)(pMsgMem) : "ASync InternetReadFileEx failed.";
+                               XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, pMsg);
+                       }
+               }
+               
+               if (inetBuffer.dwBufferLength)
+               {
+                       TCHAR * bufptr = inetBuffer.lpvBuffer;
+                       bufptr += inetBuffer.dwBufferLength;
+                       inetBuffer.lpvBuffer = bufptr;
+                       nExpected -= inetBuffer.dwBufferLength;
+                       /* Adjust inetBuffer.dwBufferLength when it is greater than the */
+                       /* expected end of file */
+                       if (inetBuffer.dwBufferLength > nExpected)
+                               inetBuffer.dwBufferLength = nExpected; 
+
+               }
+               else
+                       inetBuffer.dwBufferLength = nExpected;
+               dwErr = 0;
+       } while  (nExpected != 0);
+
+
+    /* Add to the response buffer. */ 
+       xmlrpc_mem_block_append(envP, winInetTransactionP->pResponseData, body, inetBuffer.dwBufferTotal);
+     XMLRPC_FAIL_IF_FAULT (envP);
+
+ cleanup:
+       /* Since the XMLRPC_FAIL calls goto cleanup, we must handle */
+       /* the free'ing of the memory here. */
+       if (pMsgMem != NULL)
+       {
+               LocalFree( pMsgMem );
+       }
+
+       if (body)
+               free (body);
+}
+
+
+static void
+performWinInetTransaction(xmlrpc_env *      const envP,
+                       winInetTransaction * const winInetTransactionP,
+                                          struct xmlrpc_client_transport * const clientTransportP) {
+       LPTSTR pMsg = NULL;
+       LPVOID pMsgMem = NULL;
+
+       unsigned long lastErr;
+       unsigned long reqFlags = INTERNET_FLAG_NO_UI;
+       char * acceptTypes[] = {"text/xml", NULL};
+       unsigned long queryLen = sizeof (unsigned long);
+       
+       winInetTransactionP->hURL = InternetConnect (hSyncInternetSession, 
+                                       winInetTransactionP->szHostName, winInetTransactionP->nPort, 
+                                       NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
+
+       /* Start our request running. */
+       if (winInetTransactionP->bUseSSL == TRUE)
+               reqFlags |= INTERNET_FLAG_SECURE |INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
+
+       winInetTransactionP->hHttpRequest = HttpOpenRequest (winInetTransactionP->hURL, "POST",
+               winInetTransactionP->szUrlPath, "HTTP/1.1", NULL, (const char **)&acceptTypes,
+               reqFlags, 1);
+
+       XMLRPC_FAIL_IF_NULL(winInetTransactionP->hHttpRequest,envP, XMLRPC_INTERNAL_ERROR,
+                                               "Unable to open the requested URL.");
+
+       if ( HttpAddRequestHeaders (winInetTransactionP->hHttpRequest, winInetTransactionP->headerList, 
+               strlen (winInetTransactionP->headerList), HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE ) ==FALSE)
+       {
+               XMLRPC_FAIL (envP, XMLRPC_INTERNAL_ERROR, "Could not set Content-Type.");
+       }
+
+#ifdef DEBUG
+       /* Provide the user with transport status information */
+       InternetSetStatusCallback (winInetTransactionP->hHttpRequest, statusCallback);
+#endif
+
+Again:
+       /* Send the requested XML remote procedure command */ 
+       if (HttpSendRequest (winInetTransactionP->hHttpRequest, NULL, 0, 
+               winInetTransactionP->pSendData, 
+               strlen(winInetTransactionP->pSendData))==FALSE)
+       {
+               lastErr = GetLastError ();
+
+               FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                       FORMAT_MESSAGE_IGNORE_INSERTS, 
+                       NULL,
+                       lastErr,
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                       (LPTSTR) &pMsgMem,
+                       0, NULL);
+
+
+               if (pMsgMem == NULL)
+               {
+                       switch (lastErr)
+                       {
+                       case ERROR_INTERNET_CANNOT_CONNECT:
+                               pMsg = "Sync HttpSendRequest failed: Connection refused.";
+                               break;
+                       case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
+                               pMsg = "Sync HttpSendRequest failed: Client authorization certificate needed.";
+                               break;
+
+                       /* The following conditions are recommendations that microsoft */
+                       /* provides in their knowledge base. */
+
+                       /* HOWTO: Handle Invalid Certificate Authority Error with WinInet (Q182888) */
+                       case ERROR_INTERNET_INVALID_CA:
+                               if (clientTransportP->allowInvalidSSLCerts){
+                                       OutputDebugString ("Sync HttpSendRequest failed: "
+                                               "The function is unfamiliar with the certificate "
+                                               "authority that generated the server's certificate. ");
+                                       reqFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA;
+
+                                       InternetSetOption (winInetTransactionP->hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
+                                                                               &reqFlags, sizeof (reqFlags));
+
+                                       goto Again;
+                               }
+                               else{
+                                       pMsg = "Invalid or unknown/untrusted SSL Certificate Authority.";
+                               }
+                               break;
+
+                       /* HOWTO: Make SSL Requests Using WinInet (Q168151) */
+                       case ERROR_INTERNET_SEC_CERT_CN_INVALID:
+                               if (clientTransportP->allowInvalidSSLCerts){
+                                       OutputDebugString ("Sync HttpSendRequest failed: "
+                                               "The SSL certificate common name (host name field) is incorrect\r\n "
+                                               "for example, if you entered www.server.com and the common name "
+                                               "on the certificate says www.different.com. ");
+                                       
+                                       reqFlags = INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
+
+                                       InternetSetOption (winInetTransactionP->hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
+                                                                               &reqFlags, sizeof (reqFlags));
+
+                                       goto Again;
+                               }
+                               else{
+                                       pMsg = "The SSL certificate common name (host name field) is incorrect.";
+                               }
+                               break;
+
+                       case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
+                               if (clientTransportP->allowInvalidSSLCerts){
+                                       OutputDebugString ("Sync HttpSendRequest failed: "
+                                               "The SSL certificate date that was received from the server is "
+                                               "bad. The certificate is expired. ");
+
+                                       reqFlags = INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
+
+                                       InternetSetOption (winInetTransactionP->hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
+                                                                               &reqFlags, sizeof (reqFlags));
+
+                                       goto Again;
+                               }
+                               else{
+                                       pMsg = "The SSL certificate date that was received from the server is invalid.";
+                               }
+                               break;
+
+                       default:
+                               pMsg = (LPTSTR)pMsgMem = LocalAlloc (LPTR, MAX_PATH);
+                               sprintf (pMsg, "Sync HttpSendRequest failed: GetLastError (%d)", lastErr);
+                               break;
+
+                       }
+               }
+               else
+               {
+                       pMsg = (LPTSTR)(pMsgMem); 
+
+               }
+               XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, pMsg);
+
+       }
+
+       if( HttpQueryInfo (winInetTransactionP->hHttpRequest, 
+               HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
+               &winInetTransactionP->http_status, &queryLen, NULL) == FALSE)
+       {
+               lastErr = GetLastError ();
+               FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+                       FORMAT_MESSAGE_FROM_SYSTEM, 
+                       NULL,
+                       lastErr,
+                       MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                       (LPTSTR) &pMsgMem,
+                       1024,NULL);
+
+               pMsg = (pMsgMem) ? (LPTSTR)(pMsgMem) : "Sync HttpQueryInfo failed.";
+               XMLRPC_FAIL (envP, XMLRPC_NETWORK_ERROR, pMsg);
+
+       }
+
+    /* Make sure we got a "200 OK" message from the remote server. */
+       if(winInetTransactionP->http_status!=200)
+       {
+               unsigned long msgLen = 1024;
+               char errMsg [1024];
+               *errMsg = 0;
+               HttpQueryInfo (winInetTransactionP->hHttpRequest, HTTP_QUERY_STATUS_TEXT, errMsg, &msgLen, NULL);
+
+               /* Set our fault. We break this into multiple lines because it */
+               /* will generally contain line breaks to begin with. */
+               xmlrpc_env_set_fault_formatted (envP, XMLRPC_NETWORK_ERROR,
+                                          "HTTP error #%d occurred\n %s", winInetTransactionP->http_status, errMsg);
+               goto cleanup;
+               
+        }
+    /* Read the response. */   
+    get_wininet_response (envP, winInetTransactionP);
+    XMLRPC_FAIL_IF_FAULT (envP);
+
+ cleanup:
+       /* Since the XMLRPC_FAIL calls goto cleanup, we must handle */
+       /* the free'ing of the memory here. */
+       if (pMsgMem != NULL)
+       {
+               LocalFree( pMsgMem );
+       }
+
+}
+
+static unsigned __stdcall 
+doAsyncRpc(void * arg) {
+    rpc * const rpcP = arg;
+    xmlrpc_env env;
+    xmlrpc_env_init(&env);
+    performWinInetTransaction(&env, rpcP->winInetTransactionP, rpcP->clientTransportP );
+    rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env);
+    xmlrpc_env_clean(&env);
+    return 0;
+}
+
+
+static void
+createRpcThread(xmlrpc_env *              const envP,
+                rpc *                     const rpcP,
+                pthread_t *               const threadP) {
+
+    int rc;
+
+    rc = pthread_create(threadP, NULL, doAsyncRpc, rpcP);
+    switch (rc) {
+    case 0: 
+        break;
+    case EAGAIN:
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, 
+            "pthread_create() failed:  System Resources exceeded.");
+        break;
+    case EINVAL:
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, 
+            "pthread_create() failed:  Param Error for attr.");
+        break;
+    case ENOMEM:
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, 
+            "pthread_create() failed:  No memory for new thread.");
+        break;
+    default:
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, 
+            "pthread_create() failed: Unrecognized error code %d.", rc);
+        break;
+    }
+}
+
+static void
+rpcCreate(xmlrpc_env *             const envP,
+          struct xmlrpc_client_transport * const clientTransportP,
+          const xmlrpc_server_info * const serverP,
+          xmlrpc_mem_block *       const callXmlP,
+          xmlrpc_mem_block *       const responseXmlP,
+          xmlrpc_transport_asynch_complete      complete, 
+          struct xmlrpc_call_info *       const callInfoP,
+          rpc **                   const rpcPP) {
+
+    rpc * rpcP;
+
+    MALLOCVAR(rpcP);
+    if (rpcP == NULL)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "Couldn't allocate memory for rpc object");
+    else {
+        rpcP->callInfoP = callInfoP;
+        rpcP->complete  = complete;
+        rpcP->responseXmlP = responseXmlP;
+        rpcP->threadExists = FALSE;
+
+        createWinInetTransaction(envP, serverP,
+                              callXmlP, responseXmlP, 
+                              &rpcP->winInetTransactionP);
+        if (!envP->fault_occurred) {
+            if (complete) {
+                createRpcThread(envP, rpcP, &rpcP->thread);
+                if (!envP->fault_occurred)
+                    rpcP->threadExists = TRUE;
+            }
+            if (!envP->fault_occurred) {
+                list_init_header(&rpcP->link, rpcP);
+                pthread_mutex_lock(&clientTransportP->listLock);
+                list_add_head(&clientTransportP->rpcList, &rpcP->link);
+                pthread_mutex_unlock(&clientTransportP->listLock);
+            }
+            if (envP->fault_occurred)
+                    destroyWinInetTransaction(rpcP->winInetTransactionP);
+        }
+        if (envP->fault_occurred)
+            free(rpcP);
+    }
+    *rpcPP = rpcP;
+}
+
+static void 
+rpcDestroy(rpc * const rpcP) {
+
+    XMLRPC_ASSERT_PTR_OK(rpcP);
+    XMLRPC_ASSERT(!rpcP->threadExists);
+
+    destroyWinInetTransaction(rpcP->winInetTransactionP);
+
+    list_remove(&rpcP->link);
+
+    free(rpcP);
+}
+
+static void * 
+finishRpc(struct list_head * const headerP, 
+          void *             const context ATTR_UNUSED) {
+    
+    rpc * const rpcP = headerP->itemP;
+
+    if (rpcP->threadExists) {
+        void *status;
+        int result;
+
+        result = pthread_join(rpcP->thread, &status);
+        
+        rpcP->threadExists = FALSE;
+    }
+
+    XMLRPC_MEMBLOCK_FREE(char, rpcP->responseXmlP);
+
+    rpcDestroy(rpcP);
+
+    return NULL;
+}
+
+
+/* Used for debugging purposes to track the status of
+** your request. */
+void CALLBACK statusCallback (HINTERNET hInternet,
+                         unsigned long dwContext,
+                         unsigned long dwInternetStatus,
+                         void * lpvStatusInformation,
+                         unsigned long dwStatusInformationLength)
+{
+       switch (dwInternetStatus)
+       {
+       case INTERNET_STATUS_RESOLVING_NAME:
+               OutputDebugString("INTERNET_STATUS_RESOLVING_NAME\r\n");
+               break;
+
+       case INTERNET_STATUS_NAME_RESOLVED:
+               OutputDebugString("INTERNET_STATUS_NAME_RESOLVED\r\n");
+               break;
+
+       case INTERNET_STATUS_HANDLE_CREATED:
+               OutputDebugString("INTERNET_STATUS_HANDLE_CREATED\r\n");
+               break;
+
+       case INTERNET_STATUS_CONNECTING_TO_SERVER:
+               OutputDebugString("INTERNET_STATUS_CONNECTING_TO_SERVER\r\n");
+               break;
+
+       case INTERNET_STATUS_REQUEST_SENT:
+               OutputDebugString("INTERNET_STATUS_REQUEST_SENT\r\n");
+               break;
+
+       case INTERNET_STATUS_SENDING_REQUEST:
+               OutputDebugString("INTERNET_STATUS_SENDING_REQUEST\r\n");
+               break;
+
+       case INTERNET_STATUS_CONNECTED_TO_SERVER:
+               OutputDebugString("INTERNET_STATUS_CONNECTED_TO_SERVER\r\n");
+               break;
+
+       case INTERNET_STATUS_RECEIVING_RESPONSE:
+               OutputDebugString("INTERNET_STATUS_RECEIVING_RESPONSE\r\n");
+               break;
+
+       case INTERNET_STATUS_RESPONSE_RECEIVED:
+               OutputDebugString("INTERNET_STATUS_RESPONSE_RECEIVED\r\n");
+               break;
+
+       case INTERNET_STATUS_CLOSING_CONNECTION:
+               OutputDebugString("INTERNET_STATUS_CLOSING_CONNECTION\r\n");
+               break;
+
+       case INTERNET_STATUS_CONNECTION_CLOSED:
+               OutputDebugString("INTERNET_STATUS_CONNECTION_CLOSED\r\n");
+               break;
+
+       case INTERNET_STATUS_HANDLE_CLOSING:
+               OutputDebugString("INTERNET_STATUS_HANDLE_CLOSING\r\n");
+               break;
+
+       case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
+               OutputDebugString("INTERNET_STATUS_CTL_RESPONSE_RECEIVED\r\n");
+               break;
+
+       case INTERNET_STATUS_REDIRECT:
+               OutputDebugString("INTERNET_STATUS_REDIRECT\r\n");
+               break;
+
+       case INTERNET_STATUS_REQUEST_COMPLETE:
+               /* This indicates the data is ready. */
+               OutputDebugString("INTERNET_STATUS_REQUEST_COMPLETE\r\n");
+               break;
+
+       default:
+               OutputDebugString("statusCallback, default case!\r\n");
+               break;
+     }
+}
+
+static void 
+create(xmlrpc_env *              const envP,
+       int                       const flags ATTR_UNUSED,
+       const char *              const appname ATTR_UNUSED,
+       const char *              const appversion ATTR_UNUSED,
+          const struct xmlrpc_xportparms * const transportparmsP,
+       size_t                    const parm_size,
+       struct xmlrpc_client_transport ** const handlePP) {
+/*----------------------------------------------------------------------------
+   This does the 'create' operation for a WinInet client transport.
+-----------------------------------------------------------------------------*/
+    struct xmlrpc_client_transport * transportP;
+
+       struct xmlrpc_wininet_xportparms * const wininetXportParmsP = 
+               (struct xmlrpc_wininet_xportparms *) transportparmsP;
+
+    MALLOCVAR(transportP);
+    if (transportP == NULL)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, 
+            "Unable to allocate transport descriptor.");
+    else {
+        pthread_mutex_init(&transportP->listLock, NULL);
+        
+        list_make_empty(&transportP->rpcList);
+
+               if (hSyncInternetSession == NULL)
+                       hSyncInternetSession = InternetOpen ("xmlrpc-c wininet transport",
+                               INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
+
+               if (!wininetXportParmsP || parm_size < XMLRPC_WXPSIZE(allowInvalidSSLCerts))
+                   transportP->allowInvalidSSLCerts = 0;
+               else
+            transportP->allowInvalidSSLCerts = wininetXportParmsP->allowInvalidSSLCerts;
+
+        *handlePP = transportP;
+    }
+}
+
+
+static void 
+destroy(struct xmlrpc_client_transport * const clientTransportP) {
+/*----------------------------------------------------------------------------
+   This does the 'destroy' operation for a WinInet client transport.
+-----------------------------------------------------------------------------*/
+       XMLRPC_ASSERT(clientTransportP != NULL);
+
+    XMLRPC_ASSERT(list_is_empty(&clientTransportP->rpcList));
+
+       if (hSyncInternetSession)
+               InternetCloseHandle(hSyncInternetSession);
+       hSyncInternetSession = NULL;
+
+       pthread_mutex_destroy(&clientTransportP->listLock);
+
+       free(clientTransportP);
+}
+
+
+static void 
+sendRequest(xmlrpc_env *             const envP, 
+            struct xmlrpc_client_transport * const clientTransportP,
+            const xmlrpc_server_info * const serverP,
+            xmlrpc_mem_block *       const callXmlP,
+            xmlrpc_transport_asynch_complete      complete,
+            struct xmlrpc_call_info *       const callInfoP) {
+/*----------------------------------------------------------------------------
+   Initiate an XML-RPC rpc asynchronously.  Don't wait for it to go to
+   the server.
+
+   Unless we return failure, we arrange to have complete() called when
+   the rpc completes.
+
+   This does the 'send_request' operation for a WinInet client transport.
+-----------------------------------------------------------------------------*/
+    rpc * rpcP;
+    xmlrpc_mem_block * responseXmlP;
+
+    responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+    if (!envP->fault_occurred) {
+        rpcCreate(envP, clientTransportP, serverP, callXmlP, responseXmlP,
+                  complete, callInfoP,
+                  &rpcP);
+
+        if (envP->fault_occurred)
+            XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
+    }
+    /* The user's eventual finish_asynch call will destroy this RPC
+       and response buffer
+    */
+}
+
+static void 
+finishAsynch(struct xmlrpc_client_transport * const clientTransportP,
+             xmlrpc_timeoutType         const timeoutType ATTR_UNUSED,
+             xmlrpc_timeout                const timeout ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+   Wait for the threads of all outstanding RPCs to exit and destroy those
+   RPCs.
+
+   This does the 'finish_asynch' operation for a WinInet client transport.
+-----------------------------------------------------------------------------*/
+    /* We ignore any timeout request.  Some day, we should figure out how
+       to set an alarm and interrupt running threads.
+    */
+
+    pthread_mutex_lock(&clientTransportP->listLock);
+
+    list_foreach(&clientTransportP->rpcList, finishRpc, NULL);
+
+    pthread_mutex_unlock(&clientTransportP->listLock);
+}
+
+
+static void
+call(xmlrpc_env *             const envP,
+     struct xmlrpc_client_transport * const clientTransportP,
+     const xmlrpc_server_info * const serverP,
+     xmlrpc_mem_block *       const callXmlP,
+     xmlrpc_mem_block **      const responsePP) {
+
+        
+    xmlrpc_mem_block * responseXmlP;
+    rpc * rpcP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(serverP);
+    XMLRPC_ASSERT_PTR_OK(callXmlP);
+    XMLRPC_ASSERT_PTR_OK(responsePP);
+
+    responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+    if (!envP->fault_occurred) {
+        rpcCreate(envP, clientTransportP, serverP, callXmlP, responseXmlP,
+                  NULL, NULL, &rpcP);
+        if (!envP->fault_occurred) {
+            performWinInetTransaction(envP, rpcP->winInetTransactionP, clientTransportP);
+            
+            *responsePP = responseXmlP;
+            
+            rpcDestroy(rpcP);
+        }
+        if (envP->fault_occurred)
+            XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
+    }
+}
+
+
+struct xmlrpc_client_transport_ops xmlrpc_wininet_transport_ops = {
+    NULL,
+    NULL,
+    &create,
+    &destroy,
+    &sendRequest,
+    &call,
+    &finishAsynch,
+};
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/lib/wininet_transport/xmlrpc_wininet_transport.h b/lib/wininet_transport/xmlrpc_wininet_transport.h
new file mode 100644 (file)
index 0000000..f4f0f4e
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef XMLRPC_WININET_TRANSPORT_H\r
+#define XMLRPC_WININET_TRANSPORT_H\r
+\r
+#include "xmlrpc-c/transport.h"\r
+\r
+extern struct xmlrpc_client_transport_ops xmlrpc_wininet_transport_ops;\r
+\r
+#endif\r
diff --git a/ltconfig b/ltconfig
new file mode 100755 (executable)
index 0000000..a01334f
--- /dev/null
+++ b/ltconfig
@@ -0,0 +1,3078 @@
+#! /bin/sh
+
+# ltconfig - Create a system-specific libtool.
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A lot of this script is taken from autoconf-2.10.
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+echo=echo
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec "$SHELL" "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# Find the correct PATH separator.  Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+  UNAME=${UNAME-`uname 2>/dev/null`}
+  case X$UNAME in
+    *-DOS) PATH_SEPARATOR=';' ;;
+    *)     PATH_SEPARATOR=':' ;;
+  esac
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test "X${echo_test_string+set}" != Xset; then
+  # find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+       echo_test_string="`eval $cmd`" &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
+   test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  IFS="${IFS=  }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+  for dir in $PATH /usr/ucb; do
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running ltconfig again with it.
+      ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
+    else
+      # Try using printf.
+      echo='printf "%s\n"'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+          test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+       CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+          test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+       echo="$CONFIG_SHELL $0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "$0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# The name of this program.
+progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
+
+# Constants:
+PROGRAM=ltconfig
+PACKAGE=libtool
+VERSION=1.3.4
+TIMESTAMP=" (1.385.2.196 1999/12/07 21:47:57)"
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+rm="rm -f"
+
+help="Try \`$progname --help' for more information."
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+enable_shared=yes
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+enable_static=yes
+enable_fast_install=yes
+enable_dlopen=unknown
+enable_win32_dll=no
+ltmain=
+silent=
+srcdir=
+ac_config_guess=
+ac_config_sub=
+host=
+nonopt=
+ofile="$default_ofile"
+verify_host=yes
+with_gcc=no
+with_gnu_ld=no
+need_locks=yes
+ac_ext=c
+objext=o
+libext=a
+exeext=
+cache_file=
+
+old_AR="$AR"
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+old_CPPFLAGS="$CPPFLAGS"
+old_LDFLAGS="$LDFLAGS"
+old_LD="$LD"
+old_LN_S="$LN_S"
+old_LIBS="$LIBS"
+old_NM="$NM"
+old_RANLIB="$RANLIB"
+old_DLLTOOL="$DLLTOOL"
+old_OBJDUMP="$OBJDUMP"
+old_AS="$AS"
+
+# Parse the command line options.
+args=
+prev=
+for option
+do
+  case "$option" in
+  -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$prev"; then
+    eval "$prev=\$option"
+    prev=
+    continue
+  fi
+
+  case "$option" in
+  --help) cat <<EOM
+Usage: $progname [OPTION]... [HOST [LTMAIN]]
+
+Generate a system-specific libtool script.
+
+    --debug                enable verbose shell tracing
+    --disable-shared       do not build shared libraries
+    --disable-static       do not build static libraries
+    --disable-fast-install do not optimize for fast installation
+    --enable-dlopen        enable dlopen support
+    --enable-win32-dll     enable building dlls on win32 hosts
+    --help                 display this help and exit
+    --no-verify            do not verify that HOST is a valid host type
+-o, --output=FILE          specify the output file [default=$default_ofile]
+    --quiet                same as \`--silent'
+    --silent               do not print informational messages
+    --srcdir=DIR           find \`config.guess' in DIR
+    --version              output version information and exit
+    --with-gcc             assume that the GNU C compiler will be used
+    --with-gnu-ld          assume that the C compiler uses the GNU linker
+    --disable-lock         disable file locking
+    --cache-file=FILE      configure cache file
+
+LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
+that provides basic libtool functionality.
+
+HOST is the canonical host system name [default=guessed].
+EOM
+  exit 0
+  ;;
+
+  --debug)
+    echo "$progname: enabling shell trace mode"
+    set -x
+    ;;
+
+  --disable-shared) enable_shared=no ;;
+
+  --disable-static) enable_static=no ;;
+
+  --disable-fast-install) enable_fast_install=no ;;
+
+  --enable-dlopen) enable_dlopen=yes ;;
+
+  --enable-win32-dll) enable_win32_dll=yes ;;
+
+  --quiet | --silent) silent=yes ;;
+
+  --srcdir) prev=srcdir ;;
+  --srcdir=*) srcdir="$optarg" ;;
+
+  --no-verify) verify_host=no ;;
+
+  --output | -o) prev=ofile ;;
+  --output=*) ofile="$optarg" ;;
+
+  --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
+
+  --with-gcc) with_gcc=yes ;;
+  --with-gnu-ld) with_gnu_ld=yes ;;
+
+  --disable-lock) need_locks=no ;;
+
+  --cache-file=*) cache_file="$optarg" ;;
+
+  -*)
+    echo "$progname: unrecognized option \`$option'" 1>&2
+    echo "$help" 1>&2
+    exit 1
+    ;;
+
+  *)
+    if test -z "$ltmain"; then
+      ltmain="$option"
+    elif test -z "$host"; then
+# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
+#      if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
+#        echo "$progname: warning \`$option' is not a valid host type" 1>&2
+#      fi
+      host="$option"
+    else
+      echo "$progname: too many arguments" 1>&2
+      echo "$help" 1>&2
+      exit 1
+    fi ;;
+  esac
+done
+
+if test -z "$ltmain"; then
+  echo "$progname: you must specify a LTMAIN file" 1>&2
+  echo "$help" 1>&2
+  exit 1
+fi
+
+if test ! -f "$ltmain"; then
+  echo "$progname: \`$ltmain' does not exist" 1>&2
+  echo "$help" 1>&2
+  exit 1
+fi
+
+# Quote any args containing shell metacharacters.
+ltconfig_args=
+for arg
+do
+  case "$arg" in
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ltconfig_args="$ltconfig_args '$arg'" ;;
+  *) ltconfig_args="$ltconfig_args $arg" ;;
+  esac
+done
+
+# A relevant subset of AC_INIT.
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 5 compiler messages saved in config.log
+# 6 checking for... messages and results
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>>./config.log
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi
+if test "X${LANG+set}"   = Xset; then LANG=C;   export LANG;   fi
+
+if test -n "$cache_file" && test -r "$cache_file"; then
+  echo "loading cache $cache_file within ltconfig"
+  . $cache_file
+fi
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+if test -z "$srcdir"; then
+  # Assume the source directory is the same one as the path to LTMAIN.
+  srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
+  test "$srcdir" = "$ltmain" && srcdir=.
+fi
+
+trap "$rm conftest*; exit 1" 1 2 15
+if test "$verify_host" = yes; then
+  # Check for config.guess and config.sub.
+  ac_aux_dir=
+  for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+    if test -f $ac_dir/config.guess; then
+      ac_aux_dir=$ac_dir
+      break
+    fi
+  done
+  if test -z "$ac_aux_dir"; then
+    echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
+    echo "$help" 1>&2
+    exit 1
+  fi
+  ac_config_guess=$ac_aux_dir/config.guess
+  ac_config_sub=$ac_aux_dir/config.sub
+
+  # Make sure we can run config.sub.
+  if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
+  else
+    echo "$progname: cannot run $ac_config_sub" 1>&2
+    echo "$help" 1>&2
+    exit 1
+  fi
+
+  echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+  host_alias=$host
+  case "$host_alias" in
+  "")
+    if host_alias=`$SHELL $ac_config_guess`; then :
+    else
+      echo "$progname: cannot guess host type; you must specify one" 1>&2
+      echo "$help" 1>&2
+      exit 1
+    fi ;;
+  esac
+  host=`$SHELL $ac_config_sub $host_alias`
+  echo "$ac_t$host" 1>&6
+
+  # Make sure the host verified.
+  test -z "$host" && exit 1
+
+elif test -z "$host"; then
+  echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
+  echo "$help" 1>&2
+  exit 1
+else
+  host_alias=$host
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case "$host_os" in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+case "$host_os" in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR cru $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+# Set a sane default for `AR'.
+test -z "$AR" && AR=ar
+
+# Set a sane default for `OBJDUMP'.
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+# If RANLIB is not set, then run the test.
+if test "${RANLIB+set}" != "set"; then
+  result=no
+
+  echo $ac_n "checking for ranlib... $ac_c" 1>&6
+  IFS="${IFS=  }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+  for dir in $PATH; do
+    test -z "$dir" && dir=.
+    if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
+      RANLIB="ranlib"
+      result="ranlib"
+      break
+    fi
+  done
+  IFS="$save_ifs"
+
+  echo "$ac_t$result" 1>&6
+fi
+
+if test -n "$RANLIB"; then
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+  old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+fi
+
+# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$AS" && AS=as
+
+# Check to see if we are using GCC.
+if test "$with_gcc" != yes || test -z "$CC"; then
+  # If CC is not set, then try to find GCC or a usable CC.
+  if test -z "$CC"; then
+    echo $ac_n "checking for gcc... $ac_c" 1>&6
+    IFS="${IFS=        }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+    for dir in $PATH; do
+      test -z "$dir" && dir=.
+      if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
+       CC="gcc"
+       break
+      fi
+    done
+    IFS="$save_ifs"
+
+    if test -n "$CC"; then
+      echo "$ac_t$CC" 1>&6
+    else
+      echo "$ac_t"no 1>&6
+    fi
+  fi
+
+  # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
+  if test -z "$CC"; then
+    echo $ac_n "checking for cc... $ac_c" 1>&6
+    IFS="${IFS=        }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+    cc_rejected=no
+    for dir in $PATH; do
+      test -z "$dir" && dir=.
+      if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
+       if test "$dir/cc" = "/usr/ucb/cc"; then
+         cc_rejected=yes
+         continue
+       fi
+       CC="cc"
+       break
+      fi
+    done
+    IFS="$save_ifs"
+    if test $cc_rejected = yes; then
+      # We found a bogon in the path, so make sure we never use it.
+      set dummy $CC
+      shift
+      if test $# -gt 0; then
+       # We chose a different compiler from the bogus one.
+       # However, it has the same name, so the bogon will be chosen
+       # first if we set CC to just the name; use the full file name.
+       shift
+       set dummy "$dir/cc" "$@"
+       shift
+       CC="$@"
+      fi
+    fi
+
+    if test -n "$CC"; then
+      echo "$ac_t$CC" 1>&6
+    else
+      echo "$ac_t"no 1>&6
+    fi
+
+    if test -z "$CC"; then
+      echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
+      exit 1
+    fi
+  fi
+
+  # Now see if the compiler is really GCC.
+  with_gcc=no
+  echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
+  echo "$progname:581: checking whether we are using GNU C" >&5
+
+  $rm conftest.c
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+  if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+    with_gcc=yes
+  fi
+  $rm conftest.c
+  echo "$ac_t$with_gcc" 1>&6
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo $ac_n "checking for object suffix... $ac_c" 1>&6
+$rm conftest*
+echo 'int i = 1;' > conftest.c
+echo "$progname:603: checking for object suffix" >& 5
+if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
+  # Append any warnings to the config.log.
+  cat conftest.err 1>&5
+
+  for ac_file in conftest.*; do
+    case $ac_file in
+    *.c) ;;
+    *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
+    esac
+  done
+else
+  cat conftest.err 1>&5
+  echo "$progname: failed program was:" >&5
+  cat conftest.c >&5
+fi
+$rm conftest*
+echo "$ac_t$objext" 1>&6
+
+echo $ac_n "checking for executable suffix... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_exeext="no"
+  $rm conftest*
+  echo 'main () { return 0; }' > conftest.c
+  echo "$progname:629: checking for executable suffix" >& 5
+  if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
+    # Append any warnings to the config.log.
+    cat conftest.err 1>&5
+
+    for ac_file in conftest.*; do
+      case $ac_file in
+      *.c | *.err | *.$objext ) ;;
+      *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
+      esac
+    done
+  else
+    cat conftest.err 1>&5
+    echo "$progname: failed program was:" >&5
+    cat conftest.c >&5
+  fi
+  $rm conftest*
+fi
+if test "X$ac_cv_exeext" = Xno; then
+  exeext=""
+else
+  exeext="$ac_cv_exeext"
+fi
+echo "$ac_t$ac_cv_exeext" 1>&6
+
+echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
+pic_flag=
+special_shlib_compile_flags=
+wl=
+link_static_flag=
+no_builtin_flag=
+
+if test "$with_gcc" = yes; then
+  wl='-Wl,'
+  link_static_flag='-static'
+
+  case "$host_os" in
+  beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
+    # PIC is the default for these OSes.
+    ;;
+  aix*)
+    # Below there is a dirty hack to force normal static linking with -ldl
+    # The problem is because libdl dynamically linked with both libc and
+    # libC (AIX C++ library), which obviously doesn't included in libraries
+    # list by gcc. This cause undefined symbols with -static flags.
+    # This hack allows C programs to be linked with "-static -ldl", but
+    # we not sure about C++ programs.
+    link_static_flag="$link_static_flag ${wl}-lC"
+    ;;
+  cygwin* | mingw* | os2*)
+    # We can build DLLs from non-PIC.
+    ;;
+  amigaos*)
+    # FIXME: we need at least 68020 code to build shared libraries, but
+    # adding the `-m68020' flag to GCC prevents building anything better,
+    # like `-m68040'.
+    pic_flag='-m68020 -resident32 -malways-restore-a4'
+    ;;
+  sysv4*MP*)
+    if test -d /usr/nec; then
+       pic_flag=-Kconform_pic
+    fi
+    ;;
+  *)
+    pic_flag='-fPIC'
+    ;;
+  esac
+else
+  # PORTME Check for PIC flags for the system compiler.
+  case "$host_os" in
+  aix3* | aix4*)
+    # All AIX code is PIC.
+    link_static_flag='-bnso -bI:/lib/syscalls.exp'
+    ;;
+
+  hpux9* | hpux10* | hpux11*)
+    # Is there a better link_static_flag that works with the bundled CC?
+    wl='-Wl,'
+    link_static_flag="${wl}-a ${wl}archive"
+    pic_flag='+Z'
+    ;;
+
+  irix5* | irix6*)
+    wl='-Wl,'
+    link_static_flag='-non_shared'
+    # PIC (with -KPIC) is the default.
+    ;;
+
+  cygwin* | mingw* | os2*)
+    # We can build DLLs from non-PIC.
+    ;;
+
+  osf3* | osf4* | osf5*)
+    # All OSF/1 code is PIC.
+    wl='-Wl,'
+    link_static_flag='-non_shared'
+    ;;
+
+  sco3.2v5*)
+    pic_flag='-Kpic'
+    link_static_flag='-dn'
+    special_shlib_compile_flags='-belf'
+    ;;
+
+  solaris*)
+    pic_flag='-KPIC'
+    link_static_flag='-Bstatic'
+    wl='-Wl,'
+    ;;
+
+  sunos4*)
+    pic_flag='-PIC'
+    link_static_flag='-Bstatic'
+    wl='-Qoption ld '
+    ;;
+
+  sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+    pic_flag='-KPIC'
+    link_static_flag='-Bstatic'
+    wl='-Wl,'
+    ;;
+
+  uts4*)
+    pic_flag='-pic'
+    link_static_flag='-Bstatic'
+    ;;
+  sysv4*MP*)
+    if test -d /usr/nec ;then
+      pic_flag='-Kconform_pic'
+      link_static_flag='-Bstatic'
+    fi
+    ;;
+  *)
+    can_build_shared=no
+    ;;
+  esac
+fi
+
+if test -n "$pic_flag"; then
+  echo "$ac_t$pic_flag" 1>&6
+
+  # Check to make sure the pic_flag actually works.
+  echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
+  $rm conftest*
+  echo "int some_variable = 0;" > conftest.c
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $pic_flag -DPIC"
+  echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
+  if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
+    # Append any warnings to the config.log.
+    cat conftest.err 1>&5
+    
+    case "$host_os" in
+    hpux9* | hpux10* | hpux11*)
+      # On HP-UX, both CC and GCC only warn that PIC is supported... then they
+      # create non-PIC objects.  So, if there were any warnings, we assume that
+      # PIC is not supported.
+      if test -s conftest.err; then
+       echo "$ac_t"no 1>&6
+       can_build_shared=no
+       pic_flag=
+      else
+       echo "$ac_t"yes 1>&6
+       pic_flag=" $pic_flag"
+      fi
+      ;;
+    *)
+      echo "$ac_t"yes 1>&6
+      pic_flag=" $pic_flag"
+      ;;
+    esac
+  else
+    # Append any errors to the config.log.
+    cat conftest.err 1>&5
+    can_build_shared=no
+    pic_flag=
+    echo "$ac_t"no 1>&6
+  fi
+  CFLAGS="$save_CFLAGS"
+  $rm conftest*
+else
+  echo "$ac_t"none 1>&6
+fi
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+$rm conftest*
+echo "int some_variable = 0;" > conftest.c
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory.  Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.o"
+echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
+if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
+
+  # The compiler can only warn and ignore the option if not recognized
+  # So say no if there are warnings
+    if test -s out/conftest.err; then
+      echo "$ac_t"no 1>&6
+      compiler_c_o=no
+    else
+      echo "$ac_t"yes 1>&6
+      compiler_c_o=yes
+    fi
+else
+  # Append any errors to the config.log.
+  cat out/conftest.err 1>&5
+  compiler_c_o=no
+  echo "$ac_t"no 1>&6
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+
+if test x"$compiler_c_o" = x"yes"; then
+  # Check to see if we can write to a .lo
+  echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
+  $rm conftest*
+  echo "int some_variable = 0;" > conftest.c
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -c -o conftest.lo"
+  echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
+if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
+
+    # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+      if test -s conftest.err; then
+       echo "$ac_t"no 1>&6
+       compiler_o_lo=no
+      else
+       echo "$ac_t"yes 1>&6
+       compiler_o_lo=yes
+      fi
+  else
+    # Append any errors to the config.log.
+    cat conftest.err 1>&5
+    compiler_o_lo=no
+    echo "$ac_t"no 1>&6
+  fi
+  CFLAGS="$save_CFLAGS"
+  $rm conftest*
+else
+  compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  echo "$ac_t$hard_links" 1>&6
+  $rm conftest*
+  if test "$hard_links" = no; then
+    echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+if test "$with_gcc" = yes; then
+  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+  echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
+  $rm conftest*
+  echo "int some_variable = 0;" > conftest.c
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
+  echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+  if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
+
+    # The compiler can only warn and ignore the option if not recognized
+    # So say no if there are warnings
+      if test -s conftest.err; then
+       echo "$ac_t"no 1>&6
+       compiler_rtti_exceptions=no
+      else
+       echo "$ac_t"yes 1>&6
+       compiler_rtti_exceptions=yes
+      fi
+  else
+    # Append any errors to the config.log.
+    cat conftest.err 1>&5
+    compiler_rtti_exceptions=no
+    echo "$ac_t"no 1>&6
+  fi
+  CFLAGS="$save_CFLAGS"
+  $rm conftest*
+
+  if test "$compiler_rtti_exceptions" = "yes"; then
+    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+  else
+    no_builtin_flag=' -fno-builtin'
+  fi
+  
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$special_shlib_compile_flags"; then
+  echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
+  if echo "$old_CC $old_CFLAGS " | egrep -e "[         ]$special_shlib_compile_flags[  ]" >/dev/null; then :
+  else
+    echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
+    can_build_shared=no
+  fi
+fi
+
+echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
+$rm conftest*
+echo 'main(){return(0);}' > conftest.c
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS $link_static_flag"
+echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
+if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  echo "$ac_t$link_static_flag" 1>&6
+else
+  echo "$ac_t"none 1>&6
+  link_static_flag=
+fi
+LDFLAGS="$save_LDFLAGS"
+$rm conftest*
+
+if test -z "$LN_S"; then
+  # Check to see if we can use ln -s, or we need hard links.
+  echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
+  $rm conftest.dat
+  if ln -s X conftest.dat 2>/dev/null; then
+    $rm conftest.dat
+    LN_S="ln -s"
+  else
+    LN_S=ln
+  fi
+  if test "$LN_S" = "ln -s"; then
+    echo "$ac_t"yes 1>&6
+  else
+    echo "$ac_t"no 1>&6
+  fi
+fi
+
+# Make sure LD is an absolute path.
+if test -z "$LD"; then
+  ac_prog=ld
+  if test "$with_gcc" = yes; then
+    # Check if gcc -print-prog-name=ld gives a path.
+    echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
+    echo "$progname:991: checking for ld used by GCC" >&5
+    ac_prog=`($CC -print-prog-name=ld) 2>&5`
+    case "$ac_prog" in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+    "")
+      # If it fails, then pretend we are not using GCC.
+      ac_prog=ld
+      ;;
+    *)
+      # If it is relative, then search for the first ld in PATH.
+      with_gnu_ld=unknown
+      ;;
+    esac
+  elif test "$with_gnu_ld" = yes; then
+    echo $ac_n "checking for GNU ld... $ac_c" 1>&6
+    echo "$progname:1015: checking for GNU ld" >&5
+  else
+    echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+    echo "$progname:1018: checking for non-GNU ld" >&5
+  fi
+
+  if test -z "$LD"; then
+    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+    for ac_dir in $PATH; do
+      test -z "$ac_dir" && ac_dir=.
+      if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+       LD="$ac_dir/$ac_prog"
+       # Check to see if the program is GNU ld.  I'd rather use --version,
+       # but apparently some GNU ld's only accept -v.
+       # Break only if it was the GNU/non-GNU ld that we prefer.
+       if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+         test "$with_gnu_ld" != no && break
+       else
+         test "$with_gnu_ld" != yes && break
+       fi
+      fi
+    done
+    IFS="$ac_save_ifs"
+  fi
+
+  if test -n "$LD"; then
+    echo "$ac_t$LD" 1>&6
+  else
+    echo "$ac_t"no 1>&6
+  fi
+
+  if test -z "$LD"; then
+    echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
+    exit 1
+  fi
+fi
+
+# Check to see if it really is or is not GNU ld.
+echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
+# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+echo "$ac_t$with_gnu_ld" 1>&6
+
+# See if the linker supports building shared libraries.
+echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced.  Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+
+case "$host_os" in
+cygwin* | mingw*)
+  # FIXME: the MSVC++ port hasn't been tested in a loooong time
+  # When not using gcc, we currently assume that we are using
+  # Microsoft Visual C++.
+  if test "$with_gcc" != yes; then
+    with_gnu_ld=no
+  fi
+  ;;
+
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+  # If archive_cmds runs LD, not CC, wlarc should be empty
+  wlarc='${wl}'
+
+  # See if GNU ld supports shared libraries.
+  case "$host_os" in
+  aix3* | aix4*)
+    # On AIX, the GNU linker is very broken
+    ld_shlibs=no
+    cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+    ;;
+
+  amigaos*)
+    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+
+    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+    # that the semantics of dynamic libraries on AmigaOS, at least up
+    # to version 4, is to share data among multiple programs linked
+    # with the same dynamic library.  Since this doesn't match the
+    # behavior of shared libraries on other platforms, we can use
+    # them.
+    ld_shlibs=no
+    ;;
+
+  beos*)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      allow_undefined_flag=unsupported
+      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+      # support --undefined.  This deserves some investigation.  FIXME
+      archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+
+  cygwin* | mingw*)
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec='-L$libdir'
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+
+    # Extract the symbol export list from an `--export-all' def file,
+    # then regenerate the def file from the symbol export list, so that
+    # the compiled dll only exports the symbol export list.
+    export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+      test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
+      $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def  $objdir/$soname-ltdll.$objext $libobjs $convenience~
+      sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols'
+
+    archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
+      _lt_hint=1;
+      for symbol in `cat $export_symbols`; do
+       echo "  \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def;
+       _lt_hint=`expr 1 + \$_lt_hint`;
+      done~
+      test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+      test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
+      $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+      $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+      $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
+
+      old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' 
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
+      # can we support soname and/or expsyms with a.out? -oliva
+    fi
+    ;;
+
+  solaris* | sysv5*)
+    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+      ld_shlibs=no
+      cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;      
+
+  sunos4*)
+    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
+    wlarc=
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+    else
+      ld_shlibs=no
+    fi
+    ;;
+  esac
+
+  if test "$ld_shlibs" = yes; then
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    case $host_os in
+    cygwin* | mingw*)
+      # dlltool doesn't understand --whole-archive et. al.
+      whole_archive_flag_spec=
+      ;;
+    *)
+      # ancient GNU ld didn't support --whole-archive et. al.
+      if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+        whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+        whole_archive_flag_spec=
+      fi
+      ;;
+    esac
+  fi
+else
+  # PORTME fill in a description of your system's linker (not GNU ld)
+  case "$host_os" in
+  aix3*)
+    allow_undefined_flag=unsupported
+    always_export_symbols=yes
+    archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
+    # Note: this linker hardcodes the directories in LIBPATH if there
+    # are no directories specified by -L.
+    hardcode_minus_L=yes
+    if test "$with_gcc" = yes && test -z "$link_static_flag"; then
+      # Neither direct hardcoding nor static linking is supported with a
+      # broken collect2.
+      hardcode_direct=unsupported
+    fi
+    ;;
+
+  aix4*)
+    hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
+    hardcode_libdir_separator=':'
+    if test "$with_gcc" = yes; then
+      collect2name=`${CC} -print-prog-name=collect2`
+      if test -f "$collect2name" && \
+        strings "$collect2name" | grep resolve_lib_name >/dev/null
+      then
+       # We have reworked collect2
+       hardcode_direct=yes
+      else
+       # We have old collect2
+       hardcode_direct=unsupported
+       # It fails to find uninstalled libraries when the uninstalled
+       # path is not listed in the libpath.  Setting hardcode_minus_L
+       # to unsupported forces relinking
+       hardcode_minus_L=yes
+       hardcode_libdir_flag_spec='-L$libdir'
+       hardcode_libdir_separator=
+      fi
+      shared_flag='-shared'
+    else
+      shared_flag='${wl}-bM:SRE'
+      hardcode_direct=yes
+    fi
+    allow_undefined_flag=' ${wl}-berok'
+    archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
+    archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
+    case "$host_os" in aix4.[01]|aix4.[01].*)
+      # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
+      always_export_symbols=yes ;;
+    esac
+   ;;
+
+  amigaos*)
+    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    # see comment about different semantics on the GNU ld section
+    ld_shlibs=no
+    ;;
+
+  cygwin* | mingw*)
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    # hardcode_libdir_flag_spec is actually meaningless, as there is
+    # no search path for DLLs.
+    hardcode_libdir_flag_spec=' '
+    allow_undefined_flag=unsupported
+    # Tell ltmain to make .lib files, not .a files.
+    libext=lib
+    # FIXME: Setting linknames here is a bad hack.
+    archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+    # The linker will automatically build a .lib file if we build a DLL.
+    old_archive_from_new_cmds='true'
+    # FIXME: Should let the user specify the lib program.
+    old_archive_cmds='lib /OUT:$oldlib$oldobjs'
+    fix_srcfile_path='`cygpath -w $srcfile`'
+    ;;
+
+  freebsd1*)
+    ld_shlibs=no
+    ;;
+
+  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+  # support.  Future versions do this automatically, but an explicit c++rt0.o
+  # does not break anything, and helps significantly (at the cost of a little
+  # extra space).
+  freebsd2.2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+  freebsd2*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+  freebsd*)
+    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  hpux9* | hpux10* | hpux11*)
+    case "$host_os" in
+    hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
+    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
+    esac
+    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+    hardcode_libdir_separator=:
+    hardcode_direct=yes
+    hardcode_minus_L=yes # Not in the search PATH, but as the default
+                        # location of the library.
+    export_dynamic_flag_spec='${wl}-E'
+    ;;
+
+  irix5* | irix6*)
+    if test "$with_gcc" = yes; then
+      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+    else
+      archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'  # a.out
+    else
+      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts'      # ELF
+    fi
+    hardcode_libdir_flag_spec='${wl}-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  openbsd*)
+    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_direct=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  os2*)
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_minus_L=yes
+    allow_undefined_flag=unsupported
+    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
+    old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
+    ;;
+
+  osf3*)
+    if test "$with_gcc" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  osf4* | osf5*)  # As osf3* with the addition of the -msym flag
+    if test "$with_gcc" = yes; then
+      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+    else
+      allow_undefined_flag=' -expect_unresolved \*'
+      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+    fi
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    hardcode_libdir_separator=:
+    ;;
+
+  sco3.2v5*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    hardcode_shlibpath_var=no
+    runpath_var=LD_RUN_PATH
+    hardcode_runpath_var=yes
+    ;;
+
+  solaris*)
+    no_undefined_flag=' -z text'
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
+    hardcode_libdir_flag_spec='-R$libdir'
+    hardcode_shlibpath_var=no
+    case "$host_os" in
+    solaris2.[0-5] | solaris2.[0-5].*) ;;
+    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+    esac
+    ;;
+
+  sunos4*)
+    archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_direct=yes
+    hardcode_minus_L=yes
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    hardcode_direct=no #Motorola manual says yes, but my tests say they lie 
+    ;;  
+
+  sysv4.3*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    hardcode_shlibpath_var=no
+    export_dynamic_flag_spec='-Bexport'
+    ;;
+
+  sysv5*)
+    no_undefined_flag=' -z text'
+    # $CC -shared without GNU ld will not create a library from C++
+    # object files and a static libstdc++, better avoid it by now
+    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
+    hardcode_libdir_flag_spec=
+    hardcode_shlibpath_var=no
+    runpath_var='LD_RUN_PATH'
+    ;;
+
+  uts4*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  dgux*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    hardcode_libdir_flag_spec='-L$libdir'
+    hardcode_shlibpath_var=no
+    ;;
+
+  sysv4*MP*)
+    if test -d /usr/nec; then
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+      hardcode_shlibpath_var=no
+      runpath_var=LD_RUN_PATH
+      hardcode_runpath_var=yes
+      ld_shlibs=yes
+    fi
+    ;;
+
+  sysv4.2uw2*)
+    archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts'
+    hardcode_direct=yes
+    hardcode_minus_L=no
+    hardcode_shlibpath_var=no
+    hardcode_runpath_var=yes
+    runpath_var=LD_RUN_PATH
+    ;;
+
+  unixware7*)
+    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+    runpath_var='LD_RUN_PATH'
+    hardcode_shlibpath_var=no
+    ;;
+
+  *)
+    ld_shlibs=no
+    ;;
+  esac
+fi
+echo "$ac_t$ld_shlibs" 1>&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+if test -z "$NM"; then
+  echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
+  case "$NM" in
+  [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
+  *)
+    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+    for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
+      test -z "$ac_dir" && ac_dir=.
+      if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+         NM="$ac_dir/nm -B"
+         break
+       elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+         NM="$ac_dir/nm -p"
+         break
+       else
+         NM=${NM="$ac_dir/nm"} # keep the first match, but
+         continue # so that we can try to find one that supports BSD flags
+       fi
+      fi
+    done
+    IFS="$ac_save_ifs"
+    test -z "$NM" && NM=nm
+    ;;
+  esac
+  echo "$ac_t$NM" 1>&6
+fi
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+  ;;
+irix*)
+  symcode='[BCDEGRST]'
+  ;;
+solaris*)
+  symcode='[BDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Write the raw and C identifiers.
+  global_symbol_pipe="sed -n -e 's/^.*[        ]\($symcode\)[  ][      ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+  $rm conftest*
+  cat > conftest.c <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  echo "$progname:1635: checking if global_symbol_pipe works" >&5
+  if { (eval echo $progname:1636: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { echo "$progname:1639: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
+
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+       if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
+
+         cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+         sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
+         cat <<\EOF >> conftest.c
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$objext conftstm.$objext
+         save_LIBS="$LIBS"
+         save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$objext"
+         CFLAGS="$CFLAGS$no_builtin_flag"
+         if { (eval echo $progname:1691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+           pipe_works=yes
+         else
+           echo "$progname: failed program was:" >&5
+           cat conftest.c >&5
+         fi
+         LIBS="$save_LIBS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.c >&5
+  fi
+  $rm conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    global_symbol_pipe=
+  fi
+done
+if test "$pipe_works" = yes; then
+  echo "${ac_t}ok" 1>&6
+else
+  echo "${ac_t}failed" 1>&6
+fi
+
+if test -z "$global_symbol_pipe"; then
+  global_symbol_to_cdecl=
+fi
+
+# Check hardcoding attributes.
+echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+   test -n "$runpath_var"; then
+
+  # We can hardcode non-existant directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$hardcode_shlibpath_var" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+echo "$ac_t$hardcode_action" 1>&6
+
+
+reload_flag=
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
+# PORTME Some linkers may need a different reload flag.
+reload_flag='-r'
+echo "$ac_t$reload_flag" 1>&6
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+# PORTME Fill in your ld.so characteristics
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+file_magic_cmd=
+file_magic_test_file=
+deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [regex]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
+case "$host_os" in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}.so$major'
+  ;;
+
+aix4*)
+  version_type=linux
+  # AIX has no versioning support, so currently we can not hardcode correct
+  # soname into executable. Probably we can add versioning support to
+  # collect2, so additional links can be useful in future.
+  # We preserve .a as extension for shared libraries though AIX4.2
+  # and later linker supports .so
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
+  shlibpath_var=LIBPATH
+  deplibs_check_method=pass_all
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}.so'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  deplibs_check_method=pass_all
+  lt_cv_dlopen="load_add_on"
+  lt_cv_dlopen_libs=
+  lt_cv_dlopen_self=yes
+  ;;
+
+bsdi4*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=/shlib/libc.so
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  export_dynamic_flag_spec=-rdynamic
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw*)
+  version_type=windows
+  need_version=no
+  need_lib_prefix=no
+  if test "$with_gcc" = yes; then
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
+  else
+    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
+  fi
+  dynamic_linker='Win32 ld.exe'
+  deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  file_magic_cmd='${OBJDUMP} -f'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  lt_cv_dlopen="LoadLibrary"
+  lt_cv_dlopen_libs=
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+  
+freebsd*)
+  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  version_type=freebsd-$objformat
+  case "$version_type" in
+    freebsd-elf*)
+      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
+      file_magic_cmd=/usr/bin/file
+      file_magic_test_file=`echo /usr/lib/libc.so*`
+      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      deplibs_check_method=unknown
+      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case "$host_os" in
+  freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  *) # from 3.2 on
+    shlibpath_overrides_runpath=no
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  dynamic_linker="$host_os dld.sl"
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  shlibpath_var=SHLIB_PATH
+  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+  soname_spec='${libname}${release}.sl$major'
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+irix5* | irix6*)
+  version_type=irix
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}.so.$major'
+  library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
+  case "$host_os" in
+  irix5*)
+    libsuff= shlibsuff=
+    # this will be overridden with pass_all, but let us keep it just in case
+    deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+    ;;
+  *)
+    case "$LD" in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+  deplibs_check_method='pass_all'
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+
+  if test -f /lib/ld.so.1; then
+    dynamic_linker='GNU ld.so'
+  else
+    # Only the GNU ld.so supports shared libraries on MkLinux.
+    case "$host_cpu" in
+    powerpc*) dynamic_linker=no ;;
+    *) dynamic_linker='Linux ld.so' ;;
+    esac
+  fi
+  ;;
+
+netbsd*)
+  version_type=sunos
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+    soname_spec='${libname}${release}.so$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+openbsd*)
+  version_type=sunos
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+    need_version=no
+  fi
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+os2*)
+  libname_spec='$name'
+  need_lib_prefix=no
+  library_names_spec='$libname.dll $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_version=no
+  soname_spec='${libname}${release}.so'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  # this will be overridden with pass_all, but let us keep it just in case
+  deplibs_check_method='file_magic COFF format alpha shared library'
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=/shlib/libc.so
+  deplibs_check_method='pass_all'
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+sco3.2v5*)
+  version_type=osf
+  soname_spec='${libname}${release}.so$major'
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
+  file_magic_cmd=/usr/bin/file
+  file_magic_test_file=/lib/libc.so
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case "$host_vendor" in
+    ncr)
+      deplibs_check_method='pass_all'
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+      file_magic_cmd=/usr/bin/file
+      file_magic_test_file=`echo /usr/lib/libc.so*`
+      ;;
+  esac
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+    soname_spec='$libname.so.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+echo "$ac_t$dynamic_linker" 1>&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
+
+# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
+# configure.in, otherwise build static only libraries.
+case "$host_os" in
+cygwin* | mingw* | os2*)
+  if test x$can_build_shared = xyes; then
+    test x$enable_win32_dll = xno && can_build_shared=no
+    echo "checking if package supports dlls... $can_build_shared" 1>&6
+  fi
+;;
+esac
+
+if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
+  case "$deplibs_check_method" in
+  "file_magic "*)
+    file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+    if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+       egrep "$file_magic_regex" > /dev/null; then
+      :
+    else
+      cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+    fi ;;
+  esac
+fi
+
+echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4*)
+  test "$enable_shared" = yes && enable_static=no
+  ;;
+esac
+
+echo "$ac_t$enable_shared" 1>&6
+
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+
+echo "checking whether to build static libraries... $enable_static" 1>&6
+
+if test "$hardcode_action" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+echo $ac_n "checking for objdir... $ac_c" 1>&6
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$ac_t$objdir" 1>&6
+
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
+  lt_cv_dlopen=no lt_cv_dlopen_libs=
+echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "$progname:2212: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2220 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo $progname:2233: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+echo "$progname:2252: checking for dlopen" >&5
+if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2257 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char dlopen(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+dlopen();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2282: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_dlopen=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_dlopen=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dlopen"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
+echo "$progname:2299: checking for dld_link in -ldld" >&5
+ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldld  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2307 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link();
+
+int main() {
+dld_link()
+; return 0; }
+EOF
+if { (eval echo $progname:2320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+echo "$progname:2339: checking for shl_load" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2344 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shl_load(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+shl_load();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_shl_load=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_shl_load=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="shl_load"
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+echo "$progname:2387: checking for shl_load in -ldld" >&5
+ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldld  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2395 "ltconfig"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load();
+
+int main() {
+shl_load()
+; return 0; }
+EOF
+if { (eval echo $progname:2409: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+fi
+
+    
+fi
+
+  
+fi
+
+
+fi
+
+fi
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  fi
+
+  case "$lt_cv_dlopen" in
+  dlopen)
+for ac_hdr in dlfcn.h; do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "$progname:2452: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2457 "ltconfig"
+#include <$ac_hdr>
+int fnord = 0;
+EOF
+ac_try="$ac_compile >/dev/null 2>conftest.out"
+{ (eval echo $progname:2462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+    if test "x$ac_cv_header_dlfcn_h" = xyes; then
+      CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+    fi
+    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+  echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2490: checking whether a program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self+set}" = set; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    lt_cv_dlopen_self=cross
+  else
+    cat > conftest.c <<EOF
+#line 2498 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL   RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+#  define LTDL_GLOBAL  DL_GLOBAL
+# else
+#  define LTDL_GLOBAL  0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+#  define LTDL_LAZY_OR_NOW     RTLD_LAZY
+# else
+#  ifdef DL_LAZY
+#   define LTDL_LAZY_OR_NOW    DL_LAZY
+#  else
+#   ifdef RTLD_NOW
+#    define LTDL_LAZY_OR_NOW   RTLD_NOW
+#   else
+#    ifdef DL_NOW
+#     define LTDL_LAZY_OR_NOW  DL_NOW
+#    else
+#     define LTDL_LAZY_OR_NOW  0
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+              if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } 
+
+EOF
+if { (eval echo $progname:2544: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+  lt_cv_dlopen_self=yes
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  lt_cv_dlopen_self=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self" 1>&6
+
+  if test "$lt_cv_dlopen_self" = yes; then
+    LDFLAGS="$LDFLAGS $link_static_flag"
+  echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2563: checking whether a statically linked program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    lt_cv_dlopen_self_static=cross
+  else
+    cat > conftest.c <<EOF
+#line 2571 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL   RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+#  define LTDL_GLOBAL  DL_GLOBAL
+# else
+#  define LTDL_GLOBAL  0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+#  define LTDL_LAZY_OR_NOW     RTLD_LAZY
+# else
+#  ifdef DL_LAZY
+#   define LTDL_LAZY_OR_NOW    DL_LAZY
+#  else
+#   ifdef RTLD_NOW
+#    define LTDL_LAZY_OR_NOW   RTLD_NOW
+#   else
+#    ifdef DL_NOW
+#     define LTDL_LAZY_OR_NOW  DL_NOW
+#    else
+#     define LTDL_LAZY_OR_NOW  0
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+    if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } 
+
+EOF
+if { (eval echo $progname:2617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+  lt_cv_dlopen_self_static=yes
+else
+  echo "$progname: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  lt_cv_dlopen_self_static=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
+fi
+    ;;
+  esac
+
+  case "$lt_cv_dlopen_self" in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case "$lt_cv_dlopen_self_static" in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+# Copy echo and quote the copy, instead of the original, because it is
+# used later.
+ltecho="$echo"
+if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+   ltecho="$CONFIG_SHELL \$0 --fallback-echo"
+fi
+LTSHELL="$SHELL"
+
+LTCONFIG_VERSION="$VERSION"
+
+# Only quote variables if we're using ltmain.sh.
+case "$ltmain" in
+*.sh)
+  # Now quote all the things that may contain metacharacters.
+  for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
+    old_LD old_LDFLAGS old_LIBS \
+    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
+    AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
+    reload_flag reload_cmds wl \
+    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+    library_names_spec soname_spec \
+    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
+    file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
+    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+    hardcode_libdir_flag_spec hardcode_libdir_separator  \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+    case "$var" in
+    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case "$ltecho" in
+  *'\$0 --fallback-echo"')
+    ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+    ;;
+  esac
+
+  trap "$rm \"$ofile\"; exit 1" 1 2 15
+  echo "creating $ofile"
+  $rm "$ofile"
+  cat <<EOF > "$ofile"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+### BEGIN LIBTOOL CONFIG
+EOF
+  cfgfile="$ofile"
+  ;;
+
+*)
+  # Double-quote the variables that need it (for aesthetics).
+  for var in old_CC old_CFLAGS old_CPPFLAGS \
+    old_LD old_LDFLAGS old_LIBS \
+    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
+    eval "$var=\\\"\$var\\\""
+  done
+
+  # Just create a config file.
+  cfgfile="$ofile.cfg"
+  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+  echo "creating $cfgfile"
+  $rm "$cfgfile"
+  cat <<EOF > "$cfgfile"
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+EOF
+  ;;
+esac
+
+cat <<EOF >> "$cfgfile"
+# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
+# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
+# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
+# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
+#   $0$ltconfig_args
+#
+# Compiler and other test output produced by $progname, useful for
+# debugging $progname, is in ./config.log if it exists.
+
+# The version of $progname that generated this script.
+LTCONFIG_VERSION=$LTCONFIG_VERSION
+
+# Shell to use when invoking shell scripts.
+SHELL=$LTSHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$ltecho
+
+# The archiver.
+AR=$AR
+
+# The default C compiler.
+CC=$CC
+
+# The linker used to build libraries.
+LD=$LD
+
+# Whether we need hard or soft links.
+LN_S=$LN_S
+
+# A BSD-compatible nm program.
+NM=$NM
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$reload_flag
+reload_cmds=$reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$wl
+
+# Object file suffix (normally "o").
+objext="$objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$pic_flag
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$RANLIB
+old_archive_cmds=$old_archive_cmds
+old_postinstall_cmds=$old_postinstall_cmds
+old_postuninstall_cmds=$old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$old_archive_from_new_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$archive_cmds
+archive_expsym_cmds=$archive_expsym_cmds
+postinstall_cmds=$postinstall_cmds
+postuninstall_cmds=$postuninstall_cmds
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$global_symbol_to_cdecl
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$include_expsyms
+
+EOF
+
+case "$ltmain" in
+*.sh)
+  echo '### END LIBTOOL CONFIG' >> "$ofile"
+  echo >> "$ofile"
+  case "$host_os" in
+  aix3*)
+    cat <<\EOF >> "$ofile"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  # Append the ltmain.sh script.
+  sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+
+  chmod +x "$ofile"
+  ;;
+
+*)
+  # Compile the libtool program.
+  echo "FIXME: would compile $ltmain"
+  ;;
+esac
+
+test -n "$cache_file" || exit 0
+
+# AC_CACHE_SAVE
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100644 (file)
index 0000000..50515ad
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,4012 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun ltconfig.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell, and then maybe $echo will work.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | sed 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.3.4
+TIMESTAMP=" (1.385.2.196 1999/12/07 21:47:57)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+SP2NL='tr \040 \012'
+NL2SP='tr \015\012 \040\040'
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+  save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+if test "$LTCONFIG_VERSION" != "$VERSION"; then
+  echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
+  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+  exit 1
+fi
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+  echo "$modename: not configured to build any kind of library" 1>&2
+  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+  exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+  arg="$1"
+  shift
+
+  case "$arg" in
+  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$prev"; then
+    case "$prev" in
+    execute_dlfiles)
+      eval "$prev=\"\$$prev \$arg\""
+      ;;
+    *)
+      eval "$prev=\$arg"
+      ;;
+    esac
+
+    prev=
+    prevopt=
+    continue
+  fi
+
+  # Have we seen a non-optional argument yet?
+  case "$arg" in
+  --help)
+    show_help=yes
+    ;;
+
+  --version)
+    echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+    exit 0
+    ;;
+
+  --config)
+    sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
+    exit 0
+    ;;
+
+  --debug)
+    echo "$progname: enabling shell trace mode"
+    set -x
+    ;;
+
+  --dry-run | -n)
+    run=:
+    ;;
+
+  --features)
+    echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      echo "enable shared libraries"
+    else
+      echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      echo "enable static libraries"
+    else
+      echo "disable static libraries"
+    fi
+    exit 0
+    ;;
+
+  --finish) mode="finish" ;;
+
+  --mode) prevopt="--mode" prev=mode ;;
+  --mode=*) mode="$optarg" ;;
+
+  --quiet | --silent)
+    show=:
+    ;;
+
+  -dlopen)
+    prevopt="-dlopen"
+    prev=execute_dlfiles
+    ;;
+
+  -*)
+    $echo "$modename: unrecognized option \`$arg'" 1>&2
+    $echo "$help" 1>&2
+    exit 1
+    ;;
+
+  *)
+    nonopt="$arg"
+    break
+    ;;
+  esac
+done
+
+if test -n "$prevopt"; then
+  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+  $echo "$help" 1>&2
+  exit 1
+fi
+
+if test -z "$show_help"; then
+
+  # Infer the operation mode.
+  if test -z "$mode"; then
+    case "$nonopt" in
+    *cc | *++ | gcc* | *-gcc*)
+      mode=link
+      for arg
+      do
+       case "$arg" in
+       -c)
+          mode=compile
+          break
+          ;;
+       esac
+      done
+      ;;
+    *db | *dbx | *strace | *truss)
+      mode=execute
+      ;;
+    *install*|cp|mv)
+      mode=install
+      ;;
+    *rm)
+      mode=uninstall
+      ;;
+    *)
+      # If we have no mode, but dlfiles were specified, then do execute mode.
+      test -n "$execute_dlfiles" && mode=execute
+
+      # Just use the default operation mode.
+      if test -z "$mode"; then
+       if test -n "$nonopt"; then
+         $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+       else
+         $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+       fi
+      fi
+      ;;
+    esac
+  fi
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+    $echo "$help" 1>&2
+    exit 1
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$modename --help --mode=$mode' for more information."
+
+  # These modes are in order of execution frequency so that they run quickly.
+  case "$mode" in
+  # libtool compile mode
+  compile)
+    modename="$modename: compile"
+    # Get the compilation command and the source file.
+    base_compile=
+    lastarg=
+    srcfile="$nonopt"
+    suppress_output=
+
+    user_target=no
+    for arg
+    do
+      # Accept any command-line options.
+      case "$arg" in
+      -o)
+       if test "$user_target" != "no"; then
+         $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+         exit 1
+       fi
+       user_target=next
+       ;;
+
+      -static)
+       build_old_libs=yes
+       continue
+       ;;
+      esac
+
+      case "$user_target" in
+      next)
+       # The next one is the -o target name
+       user_target=yes
+       continue
+       ;;
+      yes)
+       # We got the output file
+       user_target=set
+       libobj="$arg"
+       continue
+       ;;
+      esac
+
+      # Accept the current argument as the source file.
+      lastarg="$srcfile"
+      srcfile="$arg"
+
+      # Aesthetically quote the previous argument.
+
+      # Backslashify any backslashes, double quotes, and dollar signs.
+      # These are the only characters that are still specially
+      # interpreted inside of double-quoted scrings.
+      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+      # Double-quote args containing other shell metacharacters.
+      # Many Bourne shells cannot handle close brackets correctly in scan
+      # sets, so we specify it separately.
+      case "$lastarg" in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
+       lastarg="\"$lastarg\""
+       ;;
+      esac
+
+      # Add the previous argument to base_compile.
+      if test -z "$base_compile"; then
+       base_compile="$lastarg"
+      else
+       base_compile="$base_compile $lastarg"
+      fi
+    done
+
+    case "$user_target" in
+    set)
+      ;;
+    no)
+      # Get the name of the library object.
+      libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+      ;;
+    *)
+      $echo "$modename: you must specify a target with \`-o'" 1>&2
+      exit 1
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    xform='[cCFSfmso]'
+    case "$libobj" in
+    *.ada) xform=ada ;;
+    *.adb) xform=adb ;;
+    *.ads) xform=ads ;;
+    *.asm) xform=asm ;;
+    *.c++) xform=c++ ;;
+    *.cc) xform=cc ;;
+    *.cpp) xform=cpp ;;
+    *.cxx) xform=cxx ;;
+    *.f90) xform=f90 ;;
+    *.for) xform=for ;;
+    esac
+
+    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+    case "$libobj" in
+    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+    *)
+      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+      exit 1
+      ;;
+    esac
+
+    if test -z "$base_compile"; then
+      $echo "$modename: you must specify a compilation command" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $libobj"
+    else
+      removelist="$libobj"
+    fi
+
+    $run $rm $removelist
+    trap "$run $rm $removelist; exit 1" 1 2 15
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+      removelist="$removelist $output_obj $lockfile"
+      trap "$run $rm $removelist; exit 1" 1 2 15
+    else
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until ln "$0" "$lockfile" 2>/dev/null; do
+       $show "Waiting for $lockfile to be removed"
+       sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+       echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit 1
+      fi
+      echo $srcfile > "$lockfile"
+    fi
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      # All platforms use -DPIC, to notify preprocessed assembler code.
+      command="$base_compile $srcfile $pic_flag -DPIC"
+      if test "$build_old_libs" = yes; then
+       lo_libobj="$libobj"
+       dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+       if test "X$dir" = "X$libobj"; then
+         dir="$objdir"
+       else
+         dir="$dir/$objdir"
+       fi
+       libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+
+       if test -d "$dir"; then
+         $show "$rm $libobj"
+         $run $rm $libobj
+       else
+         $show "$mkdir $dir"
+         $run $mkdir $dir
+         status=$?
+         if test $status -ne 0 && test ! -d $dir; then
+           exit $status
+         fi
+       fi
+      fi
+      if test "$compiler_o_lo" = yes; then
+       output_obj="$libobj"
+       command="$command -o $output_obj"
+      elif test "$compiler_c_o" = yes; then
+       output_obj="$obj"
+       command="$command -o $output_obj"
+      fi
+
+      $run $rm "$output_obj"
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+       test -n "$output_obj" && $run $rm $removelist
+       exit 1
+      fi
+
+      if test "$need_locks" = warn &&
+        test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+       echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit 1
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test x"$output_obj" != x"$libobj"; then
+       $show "$mv $output_obj $libobj"
+       if $run $mv $output_obj $libobj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # If we have no pic_flag, then copy the object into place and finish.
+      if test -z "$pic_flag" && test "$build_old_libs" = yes; then
+       # Rename the .lo from within objdir to obj
+       if test -f $obj; then
+         $show $rm $obj
+         $run $rm $obj
+       fi
+
+       $show "$mv $libobj $obj"
+       if $run $mv $libobj $obj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+
+       xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+       if test "X$xdir" = "X$obj"; then
+         xdir="."
+       else
+         xdir="$xdir"
+       fi
+       baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"`
+       libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+       # Now arrange that obj and lo_libobj become the same file
+       $show "(cd $xdir && $LN_S $baseobj $libobj)"
+       if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
+         exit 0
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # Allow error messages only from the first compilation.
+      suppress_output=' >/dev/null 2>&1'
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      command="$base_compile $srcfile"
+      if test "$compiler_c_o" = yes; then
+       command="$command -o $obj"
+       output_obj="$obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      $run $rm "$output_obj"
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+       $run $rm $removelist
+       exit 1
+      fi
+
+      if test "$need_locks" = warn &&
+        test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+       echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $run $rm $removelist
+       exit 1
+      fi
+
+      # Just move the object if needed
+      if test x"$output_obj" != x"$obj"; then
+       $show "$mv $output_obj $obj"
+       if $run $mv $output_obj $obj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+
+      # Create an invalid libtool object if no PIC, so that we do not
+      # accidentally link it into a program.
+      if test "$build_libtool_libs" != yes; then
+       $show "echo timestamp > $libobj"
+       $run eval "echo timestamp > \$libobj" || exit $?
+      else
+       # Move the .lo from within objdir
+       $show "$mv $libobj $lo_libobj"
+       if $run $mv $libobj $lo_libobj; then :
+       else
+         error=$?
+         $run $rm $removelist
+         exit $error
+       fi
+      fi
+    fi
+
+    # Unlock the critical section if it was locked
+    if test "$need_locks" != no; then
+      $rm "$lockfile"
+    fi
+
+    exit 0
+    ;;
+
+  # libtool link mode
+  link)
+    modename="$modename: link"
+    case "$host" in
+    *-*-cygwin* | *-*-mingw* | *-*-os2*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invokation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+
+      # This is a source program that is used to create dlls on Windows
+      # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+      # This is a source program that is used to create import libraries
+      # on Windows for dlls which lack them. Don't remove nor modify the
+      # starting and closing comments
+# /* impgen.c starts here */
+# /*   Copyright (C) 1999 Free Software Foundation, Inc.
+# 
+#  This file is part of GNU libtool.
+# 
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+# 
+#  This program 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 General Public License for more details.
+# 
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#  */
+# 
+#  #include <stdio.h>          /* for printf() */
+#  #include <unistd.h>         /* for open(), lseek(), read() */
+#  #include <fcntl.h>          /* for O_RDONLY, O_BINARY */
+#  #include <string.h>         /* for strdup() */
+# 
+#  static unsigned int
+#  pe_get16 (fd, offset)
+#       int fd;
+#       int offset;
+#  {
+#    unsigned char b[2];
+#    lseek (fd, offset, SEEK_SET);
+#    read (fd, b, 2);
+#    return b[0] + (b[1]<<8);
+#  }
+# 
+#  static unsigned int
+#  pe_get32 (fd, offset)
+#      int fd;
+#      int offset;
+#  {
+#    unsigned char b[4];
+#    lseek (fd, offset, SEEK_SET);
+#    read (fd, b, 4);
+#    return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+#  }
+# 
+#  static unsigned int
+#  pe_as32 (ptr)
+#       void *ptr;
+#  {
+#    unsigned char *b = ptr;
+#    return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+#  }
+# 
+#  int
+#  main (argc, argv)
+#      int argc;
+#      char *argv[];
+#  {
+#      int dll;
+#      unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+#      unsigned long export_rva, export_size, nsections, secptr, expptr;
+#      unsigned long name_rvas, nexp;
+#      unsigned char *expdata, *erva;
+#      char *filename, *dll_name;
+# 
+#      filename = argv[1];
+# 
+#      dll = open(filename, O_RDONLY|O_BINARY);
+#      if (!dll)
+#      return 1;
+# 
+#      dll_name = filename;
+#    
+#      for (i=0; filename[i]; i++)
+#      if (filename[i] == '/' || filename[i] == '\\'  || filename[i] == ':')
+#          dll_name = filename + i +1;
+# 
+#      pe_header_offset = pe_get32 (dll, 0x3c);
+#      opthdr_ofs = pe_header_offset + 4 + 20;
+#      num_entries = pe_get32 (dll, opthdr_ofs + 92);
+# 
+#      if (num_entries < 1) /* no exports */
+#      return 1;
+# 
+#      export_rva = pe_get32 (dll, opthdr_ofs + 96);
+#      export_size = pe_get32 (dll, opthdr_ofs + 100);
+#      nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+#      secptr = (pe_header_offset + 4 + 20 +
+#            pe_get16 (dll, pe_header_offset + 4 + 16));
+# 
+#      expptr = 0;
+#      for (i = 0; i < nsections; i++)
+#      {
+#      char sname[8];
+#      unsigned long secptr1 = secptr + 40 * i;
+#      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+#      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+#      unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+#      lseek(dll, secptr1, SEEK_SET);
+#      read(dll, sname, 8);
+#      if (vaddr <= export_rva && vaddr+vsize > export_rva)
+#      {
+#          expptr = fptr + (export_rva - vaddr);
+#          if (export_rva + export_size > vaddr + vsize)
+#              export_size = vsize - (export_rva - vaddr);
+#          break;
+#      }
+#      }
+# 
+#      expdata = (unsigned char*)malloc(export_size);
+#      lseek (dll, expptr, SEEK_SET);
+#      read (dll, expdata, export_size);
+#      erva = expdata - export_rva;
+# 
+#      nexp = pe_as32 (expdata+24);
+#      name_rvas = pe_as32 (expdata+32);
+# 
+#      printf ("EXPORTS\n");
+#      for (i = 0; i<nexp; i++)
+#      {
+#      unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+#      printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+#      }
+# 
+#      return 0;
+#  }
+# /* impgen.c ends here */
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    compile_command="$nonopt"
+    finalize_command="$nonopt"
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    linkopts=
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      lib_search_path=
+    fi
+    # now prepend the system-specific ones
+    eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+    
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    link_against_libtool_libs=
+    ltlibs=
+    module=no
+    objs=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case "$arg" in
+      -all-static | -static)
+       if test "X$arg" = "X-all-static"; then
+         if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+           $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+         fi
+         if test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+       else
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+       fi
+       build_libtool_libs=no
+       build_old_libs=yes
+       prefer_static_libs=yes
+       break
+       ;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test $# -gt 0; do
+      arg="$1"
+      shift
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+       case "$prev" in
+       output)
+         compile_command="$compile_command @OUTPUT@"
+         finalize_command="$finalize_command @OUTPUT@"
+         ;;
+       esac
+
+       case "$prev" in
+       dlfiles|dlprefiles)
+         if test "$preload" = no; then
+           # Add the symbol object into the linking commands.
+           compile_command="$compile_command @SYMFILE@"
+           finalize_command="$finalize_command @SYMFILE@"
+           preload=yes
+         fi
+         case "$arg" in
+         *.la | *.lo) ;;  # We handle these cases below.
+         force)
+           if test "$dlself" = no; then
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         self)
+           if test "$prev" = dlprefiles; then
+             dlself=yes
+           elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+             dlself=yes
+           else
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         *)
+           if test "$prev" = dlfiles; then
+             dlfiles="$dlfiles $arg"
+           else
+             dlprefiles="$dlprefiles $arg"
+           fi
+           prev=
+           ;;
+         esac
+         ;;
+       expsyms)
+         export_symbols="$arg"
+         if test ! -f "$arg"; then
+           $echo "$modename: symbol file \`$arg' does not exist"
+           exit 1
+         fi
+         prev=
+         continue
+         ;;
+       expsyms_regex)
+         export_symbols_regex="$arg"
+         prev=
+         continue
+         ;;
+       release)
+         release="-$arg"
+         prev=
+         continue
+         ;;
+       rpath | xrpath)
+         # We need an absolute path.
+         case "$arg" in
+         [\\/]* | [A-Za-z]:[\\/]*) ;;
+         *)
+           $echo "$modename: only absolute run-paths are allowed" 1>&2
+           exit 1
+           ;;
+         esac
+         if test "$prev" = rpath; then
+           case "$rpath " in
+           *" $arg "*) ;;
+           *) rpath="$rpath $arg" ;;
+           esac
+         else
+           case "$xrpath " in
+           *" $arg "*) ;;
+           *) xrpath="$xrpath $arg" ;;
+           esac
+         fi
+         prev=
+         continue
+         ;;
+       *)
+         eval "$prev=\"\$arg\""
+         prev=
+         continue
+         ;;
+       esac
+      fi
+
+      prevarg="$arg"
+
+      case "$arg" in
+      -all-static)
+       if test -n "$link_static_flag"; then
+         compile_command="$compile_command $link_static_flag"
+         finalize_command="$finalize_command $link_static_flag"
+       fi
+       continue
+       ;;
+
+      -allow-undefined)
+       # FIXME: remove this flag sometime in the future.
+       $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+       continue
+       ;;
+
+      -avoid-version)
+       avoid_version=yes
+       continue
+       ;;
+
+      -dlopen)
+       prev=dlfiles
+       continue
+       ;;
+
+      -dlpreopen)
+       prev=dlprefiles
+       continue
+       ;;
+
+      -export-dynamic)
+       export_dynamic=yes
+       continue
+       ;;
+
+      -export-symbols | -export-symbols-regex)
+       if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+         $echo "$modename: not more than one -exported-symbols argument allowed"
+         exit 1
+       fi
+       if test "X$arg" = "X-export-symbols"; then
+         prev=expsyms
+       else
+         prev=expsyms_regex
+       fi
+       continue
+       ;;
+
+      -L*)
+       dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+       # We need an absolute path.
+       case "$dir" in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         absdir=`cd "$dir" && pwd`
+         if test -z "$absdir"; then
+           $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+           $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+           absdir="$dir"
+         fi
+         dir="$absdir"
+         ;;
+       esac
+       case " $deplibs " in
+       *" $arg "*) ;;
+       *) deplibs="$deplibs $arg";;
+       esac
+       case " $lib_search_path " in
+       *" $dir "*) ;;
+       *) lib_search_path="$lib_search_path $dir";;
+       esac
+       case "$host" in
+       *-*-cygwin* | *-*-mingw* | *-*-os2*)
+         dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+         case ":$dllsearchpath:" in
+         ::) dllsearchpath="$dllsearchdir";;
+         *":$dllsearchdir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
+         esac
+         ;;
+       esac
+       ;;
+
+      -l*)
+       if test "$arg" = "-lc"; then
+         case "$host" in
+         *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+           # These systems don't actually have c library (as such)
+           continue
+           ;;
+         esac
+       elif test "$arg" = "-lm"; then
+         case "$host" in
+         *-*-cygwin* | *-*-beos*)
+           # These systems don't actually have math library (as such)
+           continue
+           ;;
+         esac
+       fi
+       deplibs="$deplibs $arg"
+       ;;
+
+      -module)
+       module=yes
+       continue
+       ;;
+
+      -no-undefined)
+       allow_undefined=no
+       continue
+       ;;
+
+      -o) prev=output ;;
+
+      -release)
+       prev=release
+       continue
+       ;;
+
+      -rpath)
+       prev=rpath
+       continue
+       ;;
+
+      -R)
+       prev=xrpath
+       continue
+       ;;
+
+      -R*)
+       dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+       # We need an absolute path.
+       case "$dir" in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         $echo "$modename: only absolute run-paths are allowed" 1>&2
+         exit 1
+         ;;
+       esac
+       case "$xrpath " in
+       *" $dir "*) ;;
+       *) xrpath="$xrpath $dir" ;;
+       esac
+       continue
+       ;;
+
+      -static)
+       # If we have no pic_flag, then this is the same as -all-static.
+       if test -z "$pic_flag" && test -n "$link_static_flag"; then
+         compile_command="$compile_command $link_static_flag"
+         finalize_command="$finalize_command $link_static_flag"
+       fi
+       continue
+       ;;
+
+      -thread-safe)
+       thread_safe=yes
+       continue
+       ;;
+
+      -version-info)
+       prev=vinfo
+       continue
+       ;;
+
+      # Some other compiler flag.
+      -* | +*)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case "$arg" in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*)
+         arg="\"$arg\""
+         ;;
+       esac
+       ;;
+
+      *.o | *.obj | *.a | *.lib)
+       # A standard object.
+       objs="$objs $arg"
+       ;;
+
+      *.lo)
+       # A library object.
+       if test "$prev" = dlfiles; then
+         dlfiles="$dlfiles $arg"
+         if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
+           prev=
+           continue
+         else
+           # If libtool objects are unsupported, then we need to preload.
+           prev=dlprefiles
+         fi
+       fi
+
+       if test "$prev" = dlprefiles; then
+         # Preload the old-style object.
+         dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
+         prev=
+       fi
+       libobjs="$libobjs $arg"
+       ;;
+
+      *.la)
+       # A libtool-controlled library.
+
+       dlname=
+       libdir=
+       library_names=
+       old_library=
+
+       # Check to see that this really is a libtool archive.
+       if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
+         exit 1
+       fi
+
+       # If the library was installed with an old release of libtool,
+       # it will not redefine variable installed.
+       installed=yes
+
+       # Read the .la file
+       # If there is no directory component, then add one.
+       case "$arg" in
+       */* | *\\*) . $arg ;;
+       *) . ./$arg ;;
+       esac
+
+       # Get the name of the library we link against.
+       linklib=
+       for l in $old_library $library_names; do
+         linklib="$l"
+       done
+
+       if test -z "$linklib"; then
+         $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
+         exit 1
+       fi
+
+       # Find the relevant object directory and library name.
+       name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
+
+       if test "X$installed" = Xyes; then
+         dir="$libdir"
+       else
+         dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+         if test "X$dir" = "X$arg"; then
+           dir="$objdir"
+         else
+           dir="$dir/$objdir"
+         fi
+       fi
+
+       if test -n "$dependency_libs"; then
+         # Extract -R and -L from dependency_libs
+         temp_deplibs=
+         for deplib in $dependency_libs; do
+           case "$deplib" in
+           -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+                case " $rpath $xrpath " in
+                *" $temp_xrpath "*) ;;
+                *) xrpath="$xrpath $temp_xrpath";;
+                esac;;
+           -L*) case "$compile_command $temp_deplibs " in
+                *" $deplib "*) ;;
+                *) temp_deplibs="$temp_deplibs $deplib";;
+                esac
+                temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+                case " $lib_search_path " in
+                *" $temp_dir "*) ;;
+                *) lib_search_path="$lib_search_path $temp_dir";;
+                esac
+                ;;
+           *) temp_deplibs="$temp_deplibs $deplib";;
+           esac
+         done
+         dependency_libs="$temp_deplibs"
+       fi
+
+       if test -z "$libdir"; then
+         # It is a libtool convenience library, so add in its objects.
+         convenience="$convenience $dir/$old_library"
+         old_convenience="$old_convenience $dir/$old_library"
+         deplibs="$deplibs$dependency_libs"
+         compile_command="$compile_command $dir/$old_library$dependency_libs"
+         finalize_command="$finalize_command $dir/$old_library$dependency_libs"
+         continue
+       fi
+
+       # This library was specified with -dlopen.
+       if test "$prev" = dlfiles; then
+         dlfiles="$dlfiles $arg"
+         if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
+           # If there is no dlname, no dlopen support or we're linking statically,
+           # we need to preload.
+           prev=dlprefiles
+         else
+           # We should not create a dependency on this library, but we
+           # may need any libraries it requires.
+           compile_command="$compile_command$dependency_libs"
+           finalize_command="$finalize_command$dependency_libs"
+           prev=
+           continue
+         fi
+       fi
+
+       # The library was specified with -dlpreopen.
+       if test "$prev" = dlprefiles; then
+         # Prefer using a static library (so that no silly _DYNAMIC symbols
+         # are required to link).
+         if test -n "$old_library"; then
+           dlprefiles="$dlprefiles $dir/$old_library"
+         else
+           dlprefiles="$dlprefiles $dir/$linklib"
+         fi
+         prev=
+       fi
+
+       if test -n "$library_names" &&
+          { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+         link_against_libtool_libs="$link_against_libtool_libs $arg"
+         if test -n "$shlibpath_var"; then
+           # Make sure the rpath contains only unique directories.
+           case "$temp_rpath " in
+           *" $dir "*) ;;
+           *) temp_rpath="$temp_rpath $dir" ;;
+           esac
+         fi
+
+         # We need an absolute path.
+         case "$dir" in
+         [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+         *)
+           absdir=`cd "$dir" && pwd`
+           if test -z "$absdir"; then
+             $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+             $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+             absdir="$dir"
+           fi
+           ;;
+         esac
+         
+         # This is the magic to use -rpath.
+         # Skip directories that are in the system default run-time
+         # search path, unless they have been requested with -R.
+         case " $sys_lib_dlsearch_path " in
+         *" $absdir "*) ;;
+         *)
+           case "$compile_rpath " in
+           *" $absdir "*) ;;
+           *) compile_rpath="$compile_rpath $absdir" 
+           esac
+           ;;
+         esac
+
+         case " $sys_lib_dlsearch_path " in
+         *" $libdir "*) ;;
+         *)
+           case "$finalize_rpath " in
+           *" $libdir "*) ;;
+           *) finalize_rpath="$finalize_rpath $libdir"
+           esac
+           ;;
+         esac
+
+         lib_linked=yes
+         case "$hardcode_action" in
+         immediate | unsupported)
+           if test "$hardcode_direct" = no; then
+             compile_command="$compile_command $dir/$linklib"
+             deplibs="$deplibs $dir/$linklib"
+             case "$host" in
+             *-*-cygwin* | *-*-mingw* | *-*-os2*)
+               dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+               if test -n "$dllsearchpath"; then
+                 dllsearchpath="$dllsearchpath:$dllsearchdir"
+               else
+                 dllsearchpath="$dllsearchdir"
+               fi
+               ;;
+             esac
+           elif test "$hardcode_minus_L" = no; then
+             case "$host" in
+             *-*-sunos*)
+               compile_shlibpath="$compile_shlibpath$dir:"
+               ;;
+             esac
+             case "$compile_command " in
+             *" -L$dir "*) ;;
+             *) compile_command="$compile_command -L$dir";;
+             esac
+             compile_command="$compile_command -l$name"
+             deplibs="$deplibs -L$dir -l$name"
+           elif test "$hardcode_shlibpath_var" = no; then
+             case ":$compile_shlibpath:" in
+             *":$dir:"*) ;;
+             *) compile_shlibpath="$compile_shlibpath$dir:";;
+             esac
+             compile_command="$compile_command -l$name"
+             deplibs="$deplibs -l$name"
+           else
+             lib_linked=no
+           fi
+           ;;
+
+         relink)
+           if test "$hardcode_direct" = yes; then
+             compile_command="$compile_command $absdir/$linklib"
+             deplibs="$deplibs $absdir/$linklib"
+           elif test "$hardcode_minus_L" = yes; then
+             case "$compile_command " in
+             *" -L$absdir "*) ;;
+             *) compile_command="$compile_command -L$absdir";;
+             esac
+             compile_command="$compile_command -l$name"
+             deplibs="$deplibs -L$absdir -l$name"
+           elif test "$hardcode_shlibpath_var" = yes; then
+             case ":$compile_shlibpath:" in
+             *":$absdir:"*) ;;
+             *) compile_shlibpath="$compile_shlibpath$absdir:";;
+             esac
+             compile_command="$compile_command -l$name"
+             deplibs="$deplibs -l$name"
+           else
+             lib_linked=no
+           fi
+           ;;
+
+         *)
+           lib_linked=no
+           ;;
+         esac
+
+         if test "$lib_linked" != yes; then
+           $echo "$modename: configuration error: unsupported hardcode properties"
+           exit 1
+         fi
+
+         # Finalize command for both is simple: just hardcode it.
+         if test "$hardcode_direct" = yes; then
+           finalize_command="$finalize_command $libdir/$linklib"
+         elif test "$hardcode_minus_L" = yes; then
+           case "$finalize_command " in
+           *" -L$libdir "*) ;;
+           *) finalize_command="$finalize_command -L$libdir";;
+           esac
+           finalize_command="$finalize_command -l$name"
+         elif test "$hardcode_shlibpath_var" = yes; then
+           case ":$finalize_shlibpath:" in
+           *":$libdir:"*) ;;
+           *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
+           esac
+           finalize_command="$finalize_command -l$name"
+         else
+           # We cannot seem to hardcode it, guess we'll fake it.
+           case "$finalize_command " in
+           *" -L$dir "*) ;;
+           *) finalize_command="$finalize_command -L$libdir";;
+           esac
+           finalize_command="$finalize_command -l$name"
+         fi
+       else
+         # Transform directly to old archives if we don't build new libraries.
+         if test -n "$pic_flag" && test -z "$old_library"; then
+           $echo "$modename: cannot find static library for \`$arg'" 1>&2
+           exit 1
+         fi
+
+         # Here we assume that one of hardcode_direct or hardcode_minus_L
+         # is not unsupported.  This is valid on all known static and
+         # shared platforms.
+         if test "$hardcode_direct" != unsupported; then
+           test -n "$old_library" && linklib="$old_library"
+           compile_command="$compile_command $dir/$linklib"
+           finalize_command="$finalize_command $dir/$linklib"
+         else
+           case "$compile_command " in
+           *" -L$dir "*) ;;
+           *) compile_command="$compile_command -L$dir";;
+           esac
+           compile_command="$compile_command -l$name"
+           case "$finalize_command " in
+           *" -L$dir "*) ;;
+           *) finalize_command="$finalize_command -L$dir";;
+           esac
+           finalize_command="$finalize_command -l$name"
+         fi
+       fi
+
+       # Add in any libraries that this one depends upon.
+       compile_command="$compile_command$dependency_libs"
+       finalize_command="$finalize_command$dependency_libs"
+       continue
+       ;;
+
+      # Some other compiler argument.
+      *)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+       case "$arg" in
+       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*)
+         arg="\"$arg\""
+         ;;
+       esac
+       ;;
+      esac
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+      fi
+    done
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      compile_command="$compile_command $arg"
+      finalize_command="$finalize_command $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+    libobjs_save="$libobjs"
+
+    case "$output" in
+    "")
+      $echo "$modename: you must specify an output file" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+      ;;
+
+    *.a | *.lib)
+      if test -n "$link_against_libtool_libs"; then
+       $echo "$modename: error: cannot link libtool libraries into archives" 1>&2
+       exit 1
+      fi
+
+      if test -n "$deplibs"; then
+       $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+       $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+       $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+       $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+      fi
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      ;;
+
+    *.la)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case "$outputname" in
+      lib*)
+       name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+       eval libname=\"$libname_spec\"
+       ;;
+      *)
+       if test "$module" = no; then
+         $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+       fi
+       if test "$need_lib_prefix" != no; then
+         # Add the "lib" prefix for modules if required
+         name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+         eval libname=\"$libname_spec\"
+       else
+         libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+       fi
+       ;;
+      esac
+
+      output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+      if test "X$output_objdir" = "X$output"; then
+       output_objdir="$objdir"
+      else
+       output_objdir="$output_objdir/$objdir"
+      fi
+
+      if test -n "$objs"; then
+       $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
+       exit 1
+      fi
+
+      # How the heck are we supposed to write a wrapper for a shared library?
+      if test -n "$link_against_libtool_libs"; then
+        $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
+        exit 1
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
+      fi
+
+      set dummy $rpath
+      if test $# -gt 2; then
+       $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+      fi
+      install_libdir="$2"
+
+      oldlibs=
+      if test -z "$rpath"; then
+       if test "$build_libtool_libs" = yes; then
+         # Building a libtool convenience library.
+         libext=al
+         oldlibs="$output_objdir/$libname.$libext $oldlibs"
+         build_libtool_libs=convenience
+         build_old_libs=yes
+       fi
+       dependency_libs="$deplibs"
+
+       if test -n "$vinfo"; then
+         $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
+       fi
+
+       if test -n "$release"; then
+         $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+       fi
+      else
+
+       # Parse the version information argument.
+       IFS="${IFS=     }"; save_ifs="$IFS"; IFS=':'
+       set dummy $vinfo 0 0 0
+       IFS="$save_ifs"
+
+       if test -n "$8"; then
+         $echo "$modename: too many parameters to \`-version-info'" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+       fi
+
+       current="$2"
+       revision="$3"
+       age="$4"
+
+       # Check that each of the things are valid numbers.
+       case "$current" in
+       0 | [1-9] | [1-9][0-9]*) ;;
+       *)
+         $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit 1
+         ;;
+       esac
+
+       case "$revision" in
+       0 | [1-9] | [1-9][0-9]*) ;;
+       *)
+         $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit 1
+         ;;
+       esac
+
+       case "$age" in
+       0 | [1-9] | [1-9][0-9]*) ;;
+       *)
+         $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit 1
+         ;;
+       esac
+
+       if test $age -gt $current; then
+         $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+         exit 1
+       fi
+
+       # Calculate the version variables.
+       major=
+       versuffix=
+       verstring=
+       case "$version_type" in
+       none) ;;
+
+       irix)
+         major=`expr $current - $age + 1`
+         versuffix="$major.$revision"
+         verstring="sgi$major.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$revision
+         while test $loop != 0; do
+           iface=`expr $revision - $loop`
+           loop=`expr $loop - 1`
+           verstring="sgi$major.$iface:$verstring"
+         done
+         ;;
+
+       linux)
+         major=.`expr $current - $age`
+         versuffix="$major.$age.$revision"
+         ;;
+
+       osf)
+         major=`expr $current - $age`
+         versuffix=".$current.$age.$revision"
+         verstring="$current.$age.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$age
+         while test $loop != 0; do
+           iface=`expr $current - $loop`
+           loop=`expr $loop - 1`
+           verstring="$verstring:${iface}.0"
+         done
+
+         # Make executables depend on our current version.
+         verstring="$verstring:${current}.0"
+         ;;
+
+       sunos)
+         major=".$current"
+         versuffix=".$current.$revision"
+         ;;
+
+       freebsd-aout)
+         major=".$current"
+         versuffix=".$current.$revision";
+         ;;
+
+       freebsd-elf)
+         major=".$current"
+         versuffix=".$current";
+         ;;
+
+       windows)
+         # Like Linux, but with '-' rather than '.', since we only
+         # want one extension on Windows 95.
+         major=`expr $current - $age`
+         versuffix="-$major-$age-$revision"
+         ;;
+
+       *)
+         $echo "$modename: unknown library version type \`$version_type'" 1>&2
+         echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+         exit 1
+         ;;
+       esac
+
+       # Clear the version info if we defaulted, and they specified a release.
+       if test -z "$vinfo" && test -n "$release"; then
+         major=
+         verstring="0.0"
+         if test "$need_version" = no; then
+           versuffix=
+         else
+           versuffix=".0.0"
+         fi
+       fi
+
+       # Remove version info from name if versioning should be avoided
+       if test "$avoid_version" = yes && test "$need_version" = no; then
+         major=
+         versuffix=
+         verstring=""
+       fi
+       
+       # Check to see if the archive will have undefined symbols.
+       if test "$allow_undefined" = yes; then
+         if test "$allow_undefined_flag" = unsupported; then
+           $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+           build_libtool_libs=no
+           build_old_libs=yes
+         fi
+       else
+         # Don't allow undefined symbols.
+         allow_undefined_flag="$no_undefined_flag"
+       fi
+
+       dependency_libs="$deplibs"
+       case "$host" in
+       *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+         # these systems don't actually have a c library (as such)!
+         ;;
+       *)
+         # Add libc to deplibs on all other systems.
+         deplibs="$deplibs -lc"
+         ;;
+       esac
+      fi
+
+      # Create the output directory, or remove our outputs if we need to.
+      if test -d $output_objdir; then
+       $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
+       $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
+      else
+       $show "$mkdir $output_objdir"
+       $run $mkdir $output_objdir
+       status=$?
+       if test $status -ne 0 && test ! -d $output_objdir; then
+         exit $status
+       fi
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+       oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+       # Transform .lo files to .o files.
+       oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      if test "$build_libtool_libs" = yes; then
+       # Transform deplibs into only deplibs that can be linked in shared.
+       name_save=$name
+       libname_save=$libname
+       release_save=$release
+       versuffix_save=$versuffix
+       major_save=$major
+       # I'm not sure if I'm treating the release correctly.  I think
+       # release should show up in the -l (ie -lgmp5) so we don't want to
+       # add it in twice.  Is that correct?
+       release=""
+       versuffix=""
+       major=""
+       newdeplibs=
+       droppeddeps=no
+       case "$deplibs_check_method" in
+       pass_all)
+         # Don't check for shared/static.  Everything works.
+         # This might be a little naive.  We might want to check
+         # whether the library exists or not.  But this is on
+         # osf3 & osf4 and I'm not really sure... Just
+         # implementing what was already the behaviour.
+         newdeplibs=$deplibs
+         ;;
+       test_compile)
+         # This code stresses the "libraries are programs" paradigm to its
+         # limits. Maybe even breaks it.  We compile a program, linking it
+         # against the deplibs as a proxy for the library.  Then we can check
+         # whether they linked in statically or dynamically with ldd.
+         $rm conftest.c
+         cat > conftest.c <<EOF
+         int main() { return 0; }
+EOF
+         $rm conftest
+         $CC -o conftest conftest.c $deplibs
+         if test $? -eq 0 ; then
+           ldd_output=`ldd conftest`
+           for i in $deplibs; do
+             name="`expr $i : '-l\(.*\)'`"
+             # If $name is empty we are operating on a -L argument.
+             if test "$name" != "" ; then
+               libname=`eval \\$echo \"$libname_spec\"`
+               deplib_matches=`eval \\$echo \"$library_names_spec\"`
+               set dummy $deplib_matches
+               deplib_match=$2
+               if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                 newdeplibs="$newdeplibs $i"
+               else
+                 droppeddeps=yes
+                 echo
+                 echo "*** Warning: This library needs some functionality provided by $i."
+                 echo "*** I have the capability to make that library automatically link in when"
+                 echo "*** you link to this library.  But I can only do this if you have a"
+                 echo "*** shared version of the library, which you do not appear to have."
+               fi
+             else
+               newdeplibs="$newdeplibs $i"
+             fi
+           done
+         else
+           # Error occured in the first compile.  Let's try to salvage the situation:
+           # Compile a seperate program for each library.
+           for i in $deplibs; do
+             name="`expr $i : '-l\(.*\)'`"
+            # If $name is empty we are operating on a -L argument.
+             if test "$name" != "" ; then
+               $rm conftest
+               $CC -o conftest conftest.c $i
+               # Did it work?
+               if test $? -eq 0 ; then
+                 ldd_output=`ldd conftest`
+                 libname=`eval \\$echo \"$libname_spec\"`
+                 deplib_matches=`eval \\$echo \"$library_names_spec\"`
+                 set dummy $deplib_matches
+                 deplib_match=$2
+                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                   newdeplibs="$newdeplibs $i"
+                 else
+                   droppeddeps=yes
+                   echo
+                   echo "*** Warning: This library needs some functionality provided by $i."
+                   echo "*** I have the capability to make that library automatically link in when"
+                   echo "*** you link to this library.  But I can only do this if you have a"
+                   echo "*** shared version of the library, which you do not appear to have."
+                 fi
+               else
+                 droppeddeps=yes
+                 echo
+                 echo "*** Warning!  Library $i is needed by this library but I was not able to"
+                 echo "***  make it link in!  You will probably need to install it or some"
+                 echo "*** library that it depends on before this library will be fully"
+                 echo "*** functional.  Installing it before continuing would be even better."
+               fi
+             else
+               newdeplibs="$newdeplibs $i"
+             fi
+           done
+         fi
+         ;;
+       file_magic*)
+         set dummy $deplibs_check_method
+         file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
+         for a_deplib in $deplibs; do
+           name="`expr $a_deplib : '-l\(.*\)'`"
+           # If $name is empty we are operating on a -L argument.
+           if test "$name" != "" ; then
+             libname=`eval \\$echo \"$libname_spec\"`
+             for i in $lib_search_path; do
+                   potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                   for potent_lib in $potential_libs; do
+                     # Follow soft links.
+                     if ls -lLd "$potent_lib" 2>/dev/null \
+                        | grep " -> " >/dev/null; then
+                       continue 
+                     fi
+                     # The statement above tries to avoid entering an
+                     # endless loop below, in case of cyclic links.
+                     # We might still enter an endless loop, since a link
+                     # loop can be closed while we follow links,
+                     # but so what?
+                     potlib="$potent_lib"
+                     while test -h "$potlib" 2>/dev/null; do
+                       potliblink=`ls -ld $potlib | sed 's/.* -> //'`
+                       case "$potliblink" in
+                       [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+                       *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+                       esac
+                     done
+                     if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+                        | sed 10q \
+                        | egrep "$file_magic_regex" > /dev/null; then
+                       newdeplibs="$newdeplibs $a_deplib"
+                       a_deplib=""
+                       break 2
+                     fi
+                   done
+             done
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               echo
+               echo "*** Warning: This library needs some functionality provided by $a_deplib."
+               echo "*** I have the capability to make that library automatically link in when"
+               echo "*** you link to this library.  But I can only do this if you have a"
+               echo "*** shared version of the library, which you do not appear to have."
+             fi
+           else
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+           fi
+         done # Gone through all deplibs.
+         ;;
+       none | unknown | *)
+         newdeplibs=""
+         if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+              -e 's/ -[LR][^ ]*//g' -e 's/[    ]//g' |
+            grep . >/dev/null; then
+           echo
+           if test "X$deplibs_check_method" = "Xnone"; then
+             echo "*** Warning: inter-library dependencies are not supported in this platform."
+           else
+             echo "*** Warning: inter-library dependencies are not known to be supported."
+           fi
+           echo "*** All declared inter-library dependencies are being dropped."
+           droppeddeps=yes
+         fi
+         ;;
+       esac
+       versuffix=$versuffix_save
+       major=$major_save
+       release=$release_save
+       libname=$libname_save
+       name=$name_save
+
+       if test "$droppeddeps" = yes; then
+         if test "$module" = yes; then
+           echo
+           echo "*** Warning: libtool could not satisfy all declared inter-library"
+           echo "*** dependencies of module $libname.  Therefore, libtool will create"
+           echo "*** a static module, that should work as long as the dlopening"
+           echo "*** application is linked with the -dlopen flag."
+           if test -z "$global_symbol_pipe"; then
+             echo
+             echo "*** However, this would only work if libtool was able to extract symbol"
+             echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+             echo "*** not find such a program.  So, this module is probably useless."
+             echo "*** \`nm' from GNU binutils and a full rebuild may help."
+           fi
+           if test "$build_old_libs" = no; then
+             oldlibs="$output_objdir/$libname.$libext"
+             build_libtool_libs=module
+             build_old_libs=yes
+           else
+             build_libtool_libs=no
+           fi
+         else
+           echo "*** The inter-library dependencies that have been dropped here will be"
+           echo "*** automatically added whenever a program is linked with this library"
+           echo "*** or is declared to -dlopen it."
+         fi
+       fi
+       # Done checking deplibs!
+       deplibs=$newdeplibs
+      fi
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+      
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+       # Get the real and link names of the library.
+       eval library_names=\"$library_names_spec\"
+       set dummy $library_names
+       realname="$2"
+       shift; shift
+
+       if test -n "$soname_spec"; then
+         eval soname=\"$soname_spec\"
+       else
+         soname="$realname"
+       fi
+
+       lib="$output_objdir/$realname"
+       for link
+       do
+         linknames="$linknames $link"
+       done
+
+       # Ensure that we have .o objects for linkers which dislike .lo
+       # (e.g. aix) in case we are running --disable-static
+       for obj in $libobjs; do
+         xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+         if test "X$xdir" = "X$obj"; then
+           xdir="."
+         else
+           xdir="$xdir"
+         fi
+         baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+         oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+         if test ! -f $xdir/$oldobj; then
+           $show "(cd $xdir && ${LN_S} $baseobj $oldobj)"
+           $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $?
+         fi
+       done
+
+       # Use standard objects if they are pic
+       test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+       # Prepare the list of exported symbols
+       if test -z "$export_symbols"; then
+         if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+           $show "generating symbol list for \`$libname.la'"
+           export_symbols="$output_objdir/$libname.exp"
+           $run $rm $export_symbols
+           eval cmds=\"$export_symbols_cmds\"
+           IFS="${IFS=         }"; save_ifs="$IFS"; IFS='~'
+           for cmd in $cmds; do
+             IFS="$save_ifs"
+             $show "$cmd"
+             $run eval "$cmd" || exit $?
+           done
+           IFS="$save_ifs"
+           if test -n "$export_symbols_regex"; then
+             $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+             $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+             $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+             $run eval '$mv "${export_symbols}T" "$export_symbols"'
+           fi
+         fi
+       fi
+
+       if test -n "$export_symbols" && test -n "$include_expsyms"; then
+         $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+       fi
+
+       if test -n "$convenience"; then
+         if test -n "$whole_archive_flag_spec"; then
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+         else
+           gentop="$output_objdir/${outputname}x"
+           $show "${rm}r $gentop"
+           $run ${rm}r "$gentop"
+           $show "mkdir $gentop"
+           $run mkdir "$gentop"
+           status=$?
+           if test $status -ne 0 && test ! -d "$gentop"; then
+             exit $status
+           fi
+           generated="$generated $gentop"
+
+           for xlib in $convenience; do
+             # Extract the objects.
+             case "$xlib" in
+             [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+             *) xabs=`pwd`"/$xlib" ;;
+             esac
+             xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+             xdir="$gentop/$xlib"
+
+             $show "${rm}r $xdir"
+             $run ${rm}r "$xdir"
+             $show "mkdir $xdir"
+             $run mkdir "$xdir"
+             status=$?
+             if test $status -ne 0 && test ! -d "$xdir"; then
+               exit $status
+             fi
+             $show "(cd $xdir && $AR x $xabs)"
+             $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+             libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+           done
+         fi
+       fi
+
+       if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+         eval flag=\"$thread_safe_flag_spec\"
+         linkopts="$linkopts $flag"
+       fi
+
+       # Do each of the archive commands.
+       if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+         eval cmds=\"$archive_expsym_cmds\"
+       else
+         eval cmds=\"$archive_cmds\"
+       fi
+       IFS="${IFS=     }"; save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         $show "$cmd"
+         $run eval "$cmd" || exit $?
+       done
+       IFS="$save_ifs"
+
+       # Create links to the real library.
+       for linkname in $linknames; do
+         if test "$realname" != "$linkname"; then
+           $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+           $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+         fi
+       done
+
+       # If -module or -export-dynamic was specified, set the dlname.
+       if test "$module" = yes || test "$export_dynamic" = yes; then
+         # On all known operating systems, these are identical.
+         dlname="$soname"
+       fi
+      fi
+      ;;
+
+    *.lo | *.o | *.obj)
+      if test -n "$link_against_libtool_libs"; then
+       $echo "$modename: error: cannot link libtool libraries into objects" 1>&2
+       exit 1
+      fi
+
+      if test -n "$deplibs"; then
+       $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+       $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+       $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+      fi
+
+      case "$output" in
+      *.lo)
+       if test -n "$objs"; then
+         $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+         exit 1
+       fi
+       libobj="$output"
+       obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+       ;;
+      *)
+       libobj=
+       obj="$output"
+       ;;
+      esac
+
+      # Delete the old objects.
+      $run $rm $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec
+      wl= 
+
+      if test -n "$convenience"; then
+       if test -n "$whole_archive_flag_spec"; then
+         eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+       else
+         gentop="$output_objdir/${obj}x"
+         $show "${rm}r $gentop"
+         $run ${rm}r "$gentop"
+         $show "mkdir $gentop"
+         $run mkdir "$gentop"
+         status=$?
+         if test $status -ne 0 && test ! -d "$gentop"; then
+           exit $status
+         fi
+         generated="$generated $gentop"
+
+         for xlib in $convenience; do
+           # Extract the objects.
+           case "$xlib" in
+           [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+           *) xabs=`pwd`"/$xlib" ;;
+           esac
+           xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+           xdir="$gentop/$xlib"
+
+           $show "${rm}r $xdir"
+           $run ${rm}r "$xdir"
+           $show "mkdir $xdir"
+           $run mkdir "$xdir"
+           status=$?
+           if test $status -ne 0 && test ! -d "$xdir"; then
+             exit $status
+           fi
+           $show "(cd $xdir && $AR x $xabs)"
+           $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+           reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+         done
+       fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs"
+
+      output="$obj"
+      eval cmds=\"$reload_cmds\"
+      IFS="${IFS=      }"; save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+       if test -n "$gentop"; then
+         $show "${rm}r $gentop"
+         $run ${rm}r $gentop
+       fi
+
+       exit 0
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+       if test -n "$gentop"; then
+         $show "${rm}r $gentop"
+         $run ${rm}r $gentop
+       fi
+
+       # Create an invalid libtool object if no PIC, so that we don't
+       # accidentally link it into a program.
+       $show "echo timestamp > $libobj"
+       $run eval "echo timestamp > $libobj" || exit $?
+       exit 0
+      fi
+
+      if test -n "$pic_flag"; then
+       # Only do commands if we really have different PIC objects.
+       reload_objs="$libobjs $reload_conv_objs"
+       output="$libobj"
+       eval cmds=\"$reload_cmds\"
+       IFS="${IFS=     }"; save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         $show "$cmd"
+         $run eval "$cmd" || exit $?
+       done
+       IFS="$save_ifs"
+      else
+       # Just create a symlink.
+       $show $rm $libobj
+       $run $rm $libobj
+       xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+       if test "X$xdir" = "X$libobj"; then
+         xdir="."
+       else
+         xdir="$xdir"
+       fi
+       baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+       oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+       $show "(cd $xdir && $LN_S $oldobj $baseobj)"
+       $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $?
+      fi
+
+      if test -n "$gentop"; then
+       $show "${rm}r $gentop"
+       $run ${rm}r $gentop
+      fi
+
+      exit 0
+      ;;
+
+    # Anything else should be a program.
+    *)
+      if test -n "$vinfo"; then
+       $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+      fi
+
+      if test -n "$release"; then
+       $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+      fi
+
+      if test "$preload" = yes; then
+       if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
+          test "$dlopen_self_static" = unknown; then
+         $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+       fi 
+      fi
+    
+      if test -n "$rpath$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       for libdir in $rpath $xrpath; do
+         # This is the magic to use -rpath.
+         case "$compile_rpath " in
+         *" $libdir "*) ;;
+         *) compile_rpath="$compile_rpath $libdir" ;;
+         esac
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$perm_rpath " in
+         *" $libdir "*) ;;
+         *) perm_rpath="$perm_rpath $libdir" ;;
+         esac
+       fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$finalize_perm_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+         esac
+       fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+      if test "X$output_objdir" = "X$output"; then
+       output_objdir="$objdir"
+      else
+       output_objdir="$output_objdir/$objdir"
+      fi
+
+      # Create the binary in the object directory, then wrap it.
+      if test ! -d $output_objdir; then
+       $show "$mkdir $output_objdir"
+       $run $mkdir $output_objdir
+       status=$?
+       if test $status -ne 0 && test ! -d $output_objdir; then
+         exit $status
+       fi
+      fi
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+       # Transform all the library objects into standard objects.
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+       finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      dlsyms=
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       if test -n "$NM" && test -n "$global_symbol_pipe"; then
+         dlsyms="${outputname}S.c"
+       else
+         $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+       fi
+      fi
+
+      if test -n "$dlsyms"; then
+       case "$dlsyms" in
+       "") ;;
+       *.c)
+         # Discover the nlist of each of the dlfiles.
+         nlist="$output_objdir/${outputname}.nm"
+
+         $show "$rm $nlist ${nlist}S ${nlist}T"
+         $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+         # Parse the name list into a source file.
+         $show "creating $output_objdir/$dlsyms"
+
+         test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+         if test "$dlself" = yes; then
+           $show "generating symbol list for \`$output'"
+
+           test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+           # Add our own program objects to the symbol list.
+           progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+           for arg in $progfiles; do
+             $show "extracting global C symbols from \`$arg'"
+             $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+           done
+
+           if test -n "$exclude_expsyms"; then
+             $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+             $run eval '$mv "$nlist"T "$nlist"'
+           fi
+           
+           if test -n "$export_symbols_regex"; then
+             $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+             $run eval '$mv "$nlist"T "$nlist"'
+           fi
+
+           # Prepare the list of exported symbols
+           if test -z "$export_symbols"; then
+             export_symbols="$output_objdir/$output.exp"
+             $run $rm $export_symbols
+             $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+           else
+             $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+             $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+             $run eval 'mv "$nlist"T "$nlist"'
+           fi
+         fi
+
+         for arg in $dlprefiles; do
+           $show "extracting global C symbols from \`$arg'"
+           name=`echo "$arg" | sed -e 's%^.*/%%'`
+           $run eval 'echo ": $name " >> "$nlist"'
+           $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+         done
+
+         if test -z "$run"; then
+           # Make sure we have at least an empty file.
+           test -f "$nlist" || : > "$nlist"
+
+           if test -n "$exclude_expsyms"; then
+             egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+             $mv "$nlist"T "$nlist"
+           fi
+
+           # Try sorting and uniquifying the output.
+           if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
+             :
+           else
+             grep -v "^: " < "$nlist" > "$nlist"S
+           fi
+
+           if test -f "$nlist"S; then
+             eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+           else
+             echo '/* NONE */' >> "$output_objdir/$dlsyms"
+           fi
+
+           $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+           sed -n -e 's/^: \([^ ]*\) $/  {\"\1\", (lt_ptr_t) 0},/p' \
+               -e 's/^. \([^ ]*\) \([^ ]*\)$/  {"\2", (lt_ptr_t) \&\2},/p' \
+                 < "$nlist" >> "$output_objdir/$dlsyms"
+
+           $echo >> "$output_objdir/$dlsyms" "\
+  {0, (lt_ptr_t) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+         fi
+
+         pic_flag_for_symtable=
+         case "$host" in
+         # compiling the symbol table file with pic_flag works around
+         # a FreeBSD bug that causes programs to crash when -lm is
+         # linked before any other PIC object.  But we must not use
+         # pic_flag when linking with -static.  The problem exists in
+         # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+         *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)\r
+           case "$compile_command " in
+           *" -static "*) ;;
+           *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
+           esac;;
+         *-*-hpux*)
+           case "$compile_command " in
+           *" -static "*) ;;
+           *) pic_flag_for_symtable=" $pic_flag -DPIC";;
+           esac
+         esac
+
+         # Now compile the dynamic symbol file.
+         $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+         $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+         # Clean up the generated files.
+         $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+         $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+         # Transform the symbol file into the correct name.
+         compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+         finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+         ;;
+       *)
+         $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+         exit 1
+         ;;
+       esac
+      else
+       # We keep going just in case the user didn't refer to
+       # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+       # really was required.
+
+       # Nullify the symbol file.
+       compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+       finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+      fi
+
+      if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
+       # Replace the output file specification.
+       compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+       link_command="$compile_command$compile_rpath"
+
+       # We have no uninstalled library dependencies, so finalize right now.
+       $show "$link_command"
+       $run eval "$link_command"
+       status=$?
+       
+       # Delete the generated files.
+       if test -n "$dlsyms"; then
+         $show "$rm $output_objdir/${outputname}S.${objext}"
+         $run $rm "$output_objdir/${outputname}S.${objext}"
+       fi
+
+       exit $status
+      fi
+
+      if test -n "$shlibpath_var"; then
+       # We should set the shlibpath_var
+       rpath=
+       for dir in $temp_rpath; do
+         case "$dir" in
+         [\\/]* | [A-Za-z]:[\\/]*)
+           # Absolute path.
+           rpath="$rpath$dir:"
+           ;;
+         *)
+           # Relative path: add a thisdir entry.
+           rpath="$rpath\$thisdir/$dir:"
+           ;;
+         esac
+       done
+       temp_rpath="$rpath"
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+       compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+       finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+       if test -n "$perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+       if test -n "$finalize_perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $finalize_perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+      fi
+
+      if test "$hardcode_action" = relink; then
+       # Fast installation is not supported
+       link_command="$compile_var$compile_command$compile_rpath"
+       relink_command="$finalize_var$finalize_command$finalize_rpath"
+       
+       $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+       $echo "$modename: \`$output' will be relinked during installation" 1>&2
+      else
+       if test "$fast_install" != no; then
+         link_command="$finalize_var$compile_command$finalize_rpath"
+         if test "$fast_install" = yes; then
+           relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+         else
+           # fast_install is set to needless
+           relink_command=
+         fi
+       else
+         link_command="$compile_var$compile_command$compile_rpath"
+         relink_command="$finalize_var$finalize_command$finalize_rpath"
+       fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+      
+      # Delete the old output files.
+      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      $show "$link_command"
+      $run eval "$link_command" || exit $?
+
+      # Now create the wrapper script.
+      $show "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+       relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Quote $echo for shipping.
+      if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
+       case "$0" in
+       [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+       *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+       esac
+       qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+       qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if our run command is non-null.
+      if test -z "$run"; then
+       # win32 will think the script is a binary if it has
+       # a .exe suffix, so we strip it off here.
+       case $output in
+         *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
+       esac
+       $rm $output
+       trap "$rm $output; exit 1" 1 2 15
+
+       $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variable:
+  link_against_libtool_libs='$link_against_libtool_libs'
+else
+  # When we are sourced in execute mode, \$file and \$echo are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    echo=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$echo works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$echo will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+       $echo >> $output "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
+  done
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+       if test "$fast_install" = yes; then
+         echo >> $output "\
+  program=lt-'$outputname'
+  progdir=\"\$thisdir/$objdir\"
+  
+  if test ! -f \"\$progdir/\$program\" || \\
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $mkdir \"\$progdir\"
+    else
+      $rm \"\$progdir/\$file\"
+    fi"
+
+         echo >> $output "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if (cd \"\$thisdir\" && eval \$relink_command); then :
+      else
+       $rm \"\$progdir/\$file\"
+       exit 1
+      fi
+    fi
+
+    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $rm \"\$progdir/\$program\";
+      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $rm \"\$progdir/\$file\"
+  fi"
+       else
+         echo >> $output "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+       fi
+
+       echo >> $output "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+       # Export our shlibpath_var if we have one.
+       if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+         $echo >> $output "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+       fi
+
+       # fixup the dll searchpath if we need to.
+       if test -n "$dllsearchpath"; then
+         $echo >> $output "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+       fi
+
+       $echo >> $output "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+       case $host in
+       *-*-cygwin* | *-*-mingw | *-*-os2*)
+         # win32 systems need to use the prog path for dll
+         # lookup to work
+         $echo >> $output "\
+      exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+         ;;
+       *)
+         $echo >> $output "\
+      # Export the path to the program.
+      PATH=\"\$progdir:\$PATH\"
+      export PATH
+
+      exec \$program \${1+\"\$@\"}
+"
+         ;;
+       esac
+       $echo >> $output "\
+      \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+    \$echo \"This script is just a wrapper for \$program.\" 1>&2
+    echo \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+       chmod +x $output
+      fi
+      exit 0
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+       oldobjs="$libobjs_save"
+       addlibs="$convenience"
+       build_libtool_libs=no
+      else
+       if test "$build_libtool_libs" = module; then
+         oldobjs="$libobjs_save"
+         build_libtool_libs=no
+       else
+         oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+       fi
+       addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+       gentop="$output_objdir/${outputname}x"
+       $show "${rm}r $gentop"
+       $run ${rm}r "$gentop"
+       $show "mkdir $gentop"
+       $run mkdir "$gentop"
+       status=$?
+       if test $status -ne 0 && test ! -d "$gentop"; then
+         exit $status
+       fi
+       generated="$generated $gentop"
+         
+       # Add in members from convenience archives.
+       for xlib in $addlibs; do
+         # Extract the objects.
+         case "$xlib" in
+         [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+         *) xabs=`pwd`"/$xlib" ;;
+         esac
+         xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+         xdir="$gentop/$xlib"
+
+         $show "${rm}r $xdir"
+         $run ${rm}r "$xdir"
+         $show "mkdir $xdir"
+         $run mkdir "$xdir"
+         status=$?
+         if test $status -ne 0 && test ! -d "$xdir"; then
+           exit $status
+         fi
+         $show "(cd $xdir && $AR x $xabs)"
+         $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+         oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+       done
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+       eval cmds=\"$old_archive_from_new_cmds\"
+      else
+       # Ensure that we have .o objects in place in case we decided
+       # not to build a shared library, and have fallen back to building
+       # static libs even though --disable-static was passed!
+       for oldobj in $oldobjs; do
+         if test ! -f $oldobj; then
+           xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'`
+           if test "X$xdir" = "X$oldobj"; then
+             xdir="."
+           else
+             xdir="$xdir"
+           fi
+           baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'`
+           obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+           $show "(cd $xdir && ${LN_S} $obj $baseobj)"
+           $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $?
+         fi
+       done
+
+       eval cmds=\"$old_archive_cmds\"
+      fi
+      IFS="${IFS=      }"; save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$generated"; then
+      $show "${rm}r$generated"
+      $run ${rm}r$generated
+    fi
+
+    # Now create the libtool archive.
+    case "$output" in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      $show "creating $output"
+
+      if test -n "$xrpath"; then
+       temp_xrpath=
+       for libdir in $xrpath; do
+         temp_xrpath="$temp_xrpath -R$libdir"
+       done
+       dependency_libs="$temp_xrpath $dependency_libs"
+      fi
+
+      # Only create the output if not a dry run.
+      if test -z "$run"; then
+       for installed in no yes; do
+         if test "$installed" = yes; then
+           if test -z "$install_libdir"; then
+             break
+           fi
+           output="$output_objdir/$outputname"i
+         fi
+         $rm $output
+         $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$dlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'\
+"
+       done
+      fi
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+      $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
+      ;;
+    esac
+    exit 0
+    ;;
+
+  # libtool install mode
+  install)
+    modename="$modename: install"
+
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then
+      # Aesthetically quote it.
+      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+      case "$arg" in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
+       arg="\"$arg\""
+       ;;
+      esac
+      install_prog="$arg "
+      arg="$1"
+      shift
+    else
+      install_prog=
+      arg="$nonopt"
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+    case "$arg" in
+    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \      ]*|*]*)
+      arg="\"$arg\""
+      ;;
+    esac
+    install_prog="$install_prog$arg"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+       files="$files $dest"
+       dest="$arg"
+       continue
+      fi
+
+      case "$arg" in
+      -d) isdir=yes ;;
+      -f) prev="-f" ;;
+      -g) prev="-g" ;;
+      -m) prev="-m" ;;
+      -o) prev="-o" ;;
+      -s)
+       stripme=" -s"
+       continue
+       ;;
+      -*) ;;
+
+      *)
+       # If the previous option needed an argument, then skip it.
+       if test -n "$prev"; then
+         prev=
+       else
+         dest="$arg"
+         continue
+       fi
+       ;;
+      esac
+
+      # Aesthetically quote the argument.
+      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+      case "$arg" in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
+       arg="\"$arg\""
+       ;;
+      esac
+      install_prog="$install_prog $arg"
+    done
+
+    if test -z "$install_prog"; then
+      $echo "$modename: you must specify an install program" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prev' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+       $echo "$modename: no file or destination specified" 1>&2
+      else
+       $echo "$modename: you must specify a destination" 1>&2
+      fi
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    # Strip any trailing slash from the destination.
+    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+      test "X$destdir" = "X$dest" && destdir=.
+      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files
+      if test $# -gt 2; then
+       $echo "$modename: \`$dest' is not a directory" 1>&2
+       $echo "$help" 1>&2
+       exit 1
+      fi
+    fi
+    case "$destdir" in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+       case "$file" in
+       *.lo) ;;
+       *)
+         $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+         ;;
+       esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case "$file" in
+      *.a | *.lib)
+       # Do the static libraries later.
+       staticlibs="$staticlibs $file"
+       ;;
+
+      *.la)
+       # Check to see that this really is a libtool archive.
+       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+       fi
+
+       library_names=
+       old_library=
+       # If there is no directory component, then add one.
+       case "$file" in
+       */* | *\\*) . $file ;;
+       *) . ./$file ;;
+       esac
+
+       # Add the libdir to current_libdirs if it is the destination.
+       if test "X$destdir" = "X$libdir"; then
+         case "$current_libdirs " in
+         *" $libdir "*) ;;
+         *) current_libdirs="$current_libdirs $libdir" ;;
+         esac
+       else
+         # Note the libdir as a future libdir.
+         case "$future_libdirs " in
+         *" $libdir "*) ;;
+         *) future_libdirs="$future_libdirs $libdir" ;;
+         esac
+       fi
+
+       dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
+       test "X$dir" = "X$file/" && dir=
+       dir="$dir$objdir"
+
+       # See the names of the shared library.
+       set dummy $library_names
+       if test -n "$2"; then
+         realname="$2"
+         shift
+         shift
+
+         # Install the shared library and build the symlinks.
+         $show "$install_prog $dir/$realname $destdir/$realname"
+         $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
+
+         if test $# -gt 0; then
+           # Delete the old symlinks, and create new ones.
+           for linkname
+           do
+             if test "$linkname" != "$realname"; then
+               $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+               $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+             fi
+           done
+         fi
+
+         # Do each command in the postinstall commands.
+         lib="$destdir/$realname"
+         eval cmds=\"$postinstall_cmds\"
+         IFS="${IFS=   }"; save_ifs="$IFS"; IFS='~'
+         for cmd in $cmds; do
+           IFS="$save_ifs"
+           $show "$cmd"
+           $run eval "$cmd" || exit $?
+         done
+         IFS="$save_ifs"
+       fi
+
+       # Install the pseudo-library for information purposes.
+       name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+       instname="$dir/$name"i
+       $show "$install_prog $instname $destdir/$name"
+       $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+       # Maybe install the static library, too.
+       test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+       ;;
+
+      *.lo)
+       # Install (i.e. copy) a libtool object.
+
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+         destfile="$destdir/$destfile"
+       fi
+
+       # Deduce the name of the destination old-style object file.
+       case "$destfile" in
+       *.lo)
+         staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+         ;;
+       *.o | *.obj)
+         staticdest="$destfile"
+         destfile=
+         ;;
+       *)
+         $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+         ;;
+       esac
+
+       # Install the libtool object if requested.
+       if test -n "$destfile"; then
+         $show "$install_prog $file $destfile"
+         $run eval "$install_prog $file $destfile" || exit $?
+       fi
+
+       # Install the old object if enabled.
+       if test "$build_old_libs" = yes; then
+         # Deduce the name of the old-style object file.
+         staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+         $show "$install_prog $staticobj $staticdest"
+         $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+       fi
+       exit 0
+       ;;
+
+      *)
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+         destfile="$destdir/$destfile"
+       fi
+
+       # Do a test to see if this is really a libtool program.
+       if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         link_against_libtool_libs=
+         relink_command=
+
+         # If there is no directory component, then add one.
+         case "$file" in
+         */* | *\\*) . $file ;;
+         *) . ./$file ;;
+         esac
+
+         # Check the variables that should have been set.
+         if test -z "$link_against_libtool_libs"; then
+           $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
+           exit 1
+         fi
+
+         finalize=yes
+         for lib in $link_against_libtool_libs; do
+           # Check to see that each library is installed.
+           libdir=
+           if test -f "$lib"; then
+             # If there is no directory component, then add one.
+             case "$lib" in
+             */* | *\\*) . $lib ;;
+             *) . ./$lib ;;
+             esac
+           fi
+           libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
+           if test -n "$libdir" && test ! -f "$libfile"; then
+             $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+             finalize=no
+           fi
+         done
+
+         outputname=
+         if test "$fast_install" = no && test -n "$relink_command"; then
+           if test "$finalize" = yes && test -z "$run"; then
+             tmpdir="/tmp"
+             test -n "$TMPDIR" && tmpdir="$TMPDIR"
+             tmpdir="$tmpdir/libtool-$$"
+             if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+             else
+               $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+               continue
+             fi
+             outputname="$tmpdir/$file"
+             # Replace the output file specification.
+             relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+             $show "$relink_command"
+             if $run eval "$relink_command"; then :
+             else
+               $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+               ${rm}r "$tmpdir"
+               continue
+             fi
+             file="$outputname"
+           else
+             $echo "$modename: warning: cannot relink \`$file'" 1>&2
+           fi
+         else
+           # Install the binary that we compiled earlier.
+           file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+         fi
+       fi
+
+       $show "$install_prog$stripme $file $destfile"
+       $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+       test -n "$outputname" && ${rm}r "$tmpdir"
+       ;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      $show "$install_prog $file $oldlib"
+      $run eval "$install_prog \$file \$oldlib" || exit $?
+
+      # Do each command in the postinstall commands.
+      eval cmds=\"$old_postinstall_cmds\"
+      IFS="${IFS=      }"; save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+       IFS="$save_ifs"
+       $show "$cmd"
+       $run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$future_libdirs"; then
+      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+    fi
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      test -n "$run" && current_libdirs=" -n$current_libdirs"
+      exec $SHELL $0 --finish$current_libdirs
+      exit 1
+    fi
+
+    exit 0
+    ;;
+
+  # libtool finish mode
+  finish)
+    modename="$modename: finish"
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+       libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+       if test -n "$finish_cmds"; then
+         # Do each command in the finish commands.
+         eval cmds=\"$finish_cmds\"
+         IFS="${IFS=   }"; save_ifs="$IFS"; IFS='~'
+         for cmd in $cmds; do
+           IFS="$save_ifs"
+           $show "$cmd"
+           $run eval "$cmd" || admincmds="$admincmds
+       $cmd"
+         done
+         IFS="$save_ifs"
+       fi
+       if test -n "$finish_eval"; then
+         # Do the single finish_eval.
+         eval cmds=\"$finish_eval\"
+         $run eval "$cmds" || admincmds="$admincmds
+       $cmds"
+       fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    test "$show" = : && exit 0
+
+    echo "----------------------------------------------------------------------"
+    echo "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      echo "   $libdir"
+    done
+    echo
+    echo "If you ever happen to want to link against installed libraries"
+    echo "in a given directory, LIBDIR, you must either use libtool, and"
+    echo "specify the full pathname of the library, or use \`-LLIBDIR'"
+    echo "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      echo "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      echo "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      echo "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      echo "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    echo
+    echo "See any operating system documentation about shared libraries for"
+    echo "more information, such as the ld(1) and ld.so(8) manual pages."
+    echo "----------------------------------------------------------------------"
+    exit 0
+    ;;
+
+  # libtool execute mode
+  execute)
+    modename="$modename: execute"
+
+    # The first argument is the command name.
+    cmd="$nonopt"
+    if test -z "$cmd"; then
+      $echo "$modename: you must specify a COMMAND" 1>&2
+      $echo "$help"
+      exit 1
+    fi
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      if test ! -f "$file"; then
+       $echo "$modename: \`$file' is not a file" 1>&2
+       $echo "$help" 1>&2
+       exit 1
+      fi
+
+      dir=
+      case "$file" in
+      *.la)
+       # Check to see that this really is a libtool archive.
+       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+       else
+         $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+         $echo "$help" 1>&2
+         exit 1
+       fi
+
+       # Read the libtool library.
+       dlname=
+       library_names=
+
+       # If there is no directory component, then add one.
+       case "$file" in
+       */* | *\\*) . $file ;;
+       *) . ./$file ;;
+       esac
+
+       # Skip this library if it cannot be dlopened.
+       if test -z "$dlname"; then
+         # Warn if it was a shared library.
+         test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+         continue
+       fi
+
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$dir" = "X$file" && dir=.
+
+       if test -f "$dir/$objdir/$dlname"; then
+         dir="$dir/$objdir"
+       else
+         $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+         exit 1
+       fi
+       ;;
+
+      *.lo)
+       # Just add the directory containing the .lo file.
+       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+       test "X$dir" = "X$file" && dir=.
+       ;;
+
+      *)
+       $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+       continue
+       ;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+       eval "$shlibpath_var=\"\$dir\""
+      else
+       eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case "$file" in
+      -*) ;;
+      *)
+       # Do a test to see if this is really a libtool program.
+       if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         # If there is no directory component, then add one.
+         case "$file" in
+         */* | *\\*) . $file ;;
+         *) . ./$file ;;
+         esac
+
+         # Transform arg to wrapped name.
+         file="$progdir/$program"
+       fi
+       ;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+      args="$args \"$file\""
+    done
+
+    if test -z "$run"; then
+      if test -n "$shlibpath_var"; then
+        # Export the shlibpath_var.
+        eval "export $shlibpath_var"
+      fi
+
+      # Restore saved enviroment variables
+      if test "${save_LC_ALL+set}" = set; then
+       LC_ALL="$save_LC_ALL"; export LC_ALL
+      fi
+      if test "${save_LANG+set}" = set; then
+       LANG="$save_LANG"; export LANG
+      fi
+
+      # Now actually exec the command.
+      eval "exec \$cmd$args"
+
+      $echo "$modename: cannot exec \$cmd$args"
+      exit 1
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+        eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+        $echo "export $shlibpath_var"
+      fi
+      $echo "$cmd$args"
+      exit 0
+    fi
+    ;;
+
+  # libtool uninstall mode
+  uninstall)
+    modename="$modename: uninstall"
+    rm="$nonopt"
+    files=
+
+    for arg
+    do
+      case "$arg" in
+      -*) rm="$rm $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    if test -z "$rm"; then
+      $echo "$modename: you must specify an RM program" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    for file in $files; do
+      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+      test "X$dir" = "X$file" && dir=.
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+      rmfiles="$file"
+
+      case "$name" in
+      *.la)
+       # Possibly a libtool archive, so verify it.
+       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+         . $dir/$name
+
+         # Delete the libtool libraries and symlinks.
+         for n in $library_names; do
+           rmfiles="$rmfiles $dir/$n"
+         done
+         test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
+
+         $show "$rm $rmfiles"
+         $run $rm $rmfiles
+
+         if test -n "$library_names"; then
+           # Do each command in the postuninstall commands.
+           eval cmds=\"$postuninstall_cmds\"
+           IFS="${IFS=         }"; save_ifs="$IFS"; IFS='~'
+           for cmd in $cmds; do
+             IFS="$save_ifs"
+             $show "$cmd"
+             $run eval "$cmd"
+           done
+           IFS="$save_ifs"
+         fi
+
+         if test -n "$old_library"; then
+           # Do each command in the old_postuninstall commands.
+           eval cmds=\"$old_postuninstall_cmds\"
+           IFS="${IFS=         }"; save_ifs="$IFS"; IFS='~'
+           for cmd in $cmds; do
+             IFS="$save_ifs"
+             $show "$cmd"
+             $run eval "$cmd"
+           done
+           IFS="$save_ifs"
+         fi
+
+         # FIXME: should reinstall the best remaining shared library.
+       fi
+       ;;
+
+      *.lo)
+       if test "$build_old_libs" = yes; then
+         oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
+         rmfiles="$rmfiles $dir/$oldobj"
+       fi
+       $show "$rm $rmfiles"
+       $run $rm $rmfiles
+       ;;
+
+      *)
+       $show "$rm $rmfiles"
+       $run $rm $rmfiles
+       ;;
+      esac
+    done
+    exit 0
+    ;;
+
+  "")
+    $echo "$modename: you must specify a MODE" 1>&2
+    $echo "$generic_help" 1>&2
+    exit 1
+    ;;
+  esac
+
+  $echo "$modename: invalid operation mode \`$mode'" 1>&2
+  $echo "$generic_help" 1>&2
+  exit 1
+fi # test -z "$show_help"
+
+# We need to display help for each of the modes.
+case "$mode" in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+    --config          show all configuration variables
+    --debug           enable verbose shell tracing
+-n, --dry-run         display commands without modifying any files
+    --features        display basic configuration information and exit
+    --finish          same as \`--mode=finish'
+    --help            display this help message and exit
+    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
+    --quiet           same as \`--silent'
+    --silent          don't print informational messages
+    --version         print version information
+
+MODE must be one of the following:
+
+      compile         compile a source file into a libtool object
+      execute         automatically set library path, then run a program
+      finish          complete the installation of libtool libraries
+      install         install libraries or executables
+      link            create a library or an executable
+      uninstall       remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE."
+  exit 0
+  ;;
+
+compile)
+  $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -static           always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+  ;;
+
+execute)
+  $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+  ;;
+
+finish)
+  $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+  ;;
+
+install)
+  $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+  ;;
+
+link)
+  $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                   try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                   try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -static           do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                   specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+  ;;
+
+uninstall)
+  $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+*)
+  $echo "$modename: invalid operation mode \`$mode'" 1>&2
+  $echo "$help" 1>&2
+  exit 1
+  ;;
+esac
+
+echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/missing b/missing
new file mode 100755 (executable)
index 0000000..7789652
--- /dev/null
+++ b/missing
@@ -0,0 +1,190 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing - GNU libit 0.0"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acinclude.m4' or \`configure.in'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`configure.in'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acconfig.h' or \`configure.in'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+                                      sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+          sed 's/\.am$/.in/' |
+          while read f; do touch "$f"; done
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.y)
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.c
+           fi
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.h
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f y.tab.h ]; then
+       echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+       echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.l)
+           SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" lex.yy.c
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+       echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  makeinfo)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequirements for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755 (executable)
index 0000000..4f58503
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp"
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+         errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644 (file)
index 0000000..f4d6229
--- /dev/null
@@ -0,0 +1,5 @@
+rpctest
+rpctest.static
+cpptest
+efrpctest
+efrpctest_wrapper
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..e78370d
--- /dev/null
@@ -0,0 +1,203 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/..
+endif
+SUBDIR = src
+BUILDDIR = $(SRCDIR)
+VPATH = .:$(SRCDIR)
+
+include $(BUILDDIR)/Makefile.config
+
+ABYSS_LIBDIR = $(BUILDDIR)/lib/abyss/src/.libs
+LIBUTIL_LIBDIR = $(BUILDDIR)/lib/libutil/.libs
+
+default: all
+
+SUBDIRS =
+
+ifeq ($(ENABLE_CPLUSPLUS),yes)
+  SUBDIRS += cpp
+endif
+
+WININET_TRANSPORT_DIR = $(SRCDIR)/lib/wininet_transport
+CURL_TRANSPORT_DIR    = $(SRCDIR)/lib/curl_transport
+LIBWWW_TRANSPORT_DIR  = $(SRCDIR)/lib/libwww_transport
+
+# TRANSPORT_OBJS is the list of modules that have to go into the client
+# library to provide the client XML transport functions.  Since there is
+# some variability in what XML transports we can build into the client
+# library, this is a little complicated.
+
+# TRANSPORT_LIBDEP is linker -l options to declare what libraries contain
+# things to which the transport objects refer.  (like LIBxxx_LIBDEP --
+# see below)
+
+TRANSPORT_OBJS =
+TRANSPORT_LIBDEP =
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+  TRANSPORT_OBJS += $(WININET_TRANSPORT_DIR)/xmlrpc_wininet_transport.lo
+  TRANSPORT_LIBDEP += $(shell wininet-config --libs)
+endif
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+  TRANSPORT_OBJS += $(CURL_TRANSPORT_DIR)/xmlrpc_curl_transport.lo
+  TRANSPORT_LIBDEP += $(shell curl-config --libs)
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+  TRANSPORT_OBJS += $(LIBWWW_TRANSPORT_DIR)/xmlrpc_libwww_transport.lo
+  TRANSPORT_LIBDEP += $(shell libwww-config --libs)
+endif
+
+ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
+  LIBXML_INCLUDES = $(shell xml2-config --cflags)
+  LIBXML_LIBS = $(shell xml2-config --libs)
+else
+  LIBXML_INCLUDES = -I$(SRCDIR)/lib/expat/xmlparse
+endif
+
+ABYSS_INCLUDES = -I$(SRCDIR)/lib/abyss/src
+
+ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
+  XMLRPC_XML_PARSER = xmlrpc_libxml2.lo
+else
+  XMLRPC_XML_PARSER = xmlrpc_expat.lo
+endif
+
+# LIBxxx_OBJS is the list of object files that make up library libxxx.
+
+# LIBxxx_LIBDEP is linker -l options to declare what libraries contain
+# things to which the library being built refers.  This information
+# makes its way to the dynamic linker, so it knows to load the
+# referred-to library before it loads libxxx.  Note that the link command
+# may require the necessary -L options in addition.
+
+LIBXMLRPC_CLIENT_OBJS = xmlrpc_client.lo xmlrpc_client_global.lo
+LIBXMLRPC_CLIENT_LIBDEP = -lxmlrpc_util -lxmlrpc
+
+LIBXMLRPC_SERVER_OBJS = registry.lo system_method.lo
+LIBXMLRPC_SERVER_LIBDEP = -lxmlrpc_util -lxmlrpc
+
+LIBXMLRPC_SERVER_ABYSS_OBJS = xmlrpc_server_abyss.lo
+LIBXMLRPC_SERVER_ABYSS_LIBDEP = \
+  -lxmlrpc_util -lxmlrpc_server -L$(ABYSS_LIBDIR) -lxmlrpc_abyss -lxmlrpc
+
+LIBXMLRPC_SERVER_CGI_OBJS = xmlrpc_server_cgi.lo
+LIBXMLRPC_SERVER_CGI_LIBDEP = -lxmlrpc_util -lxmlrpc_server -lxmlrpc
+
+LIBXMLRPC_OBJS = \
+       trace.lo \
+       xmlrpc_data.lo \
+       xmlrpc_builddecomp.lo \
+       xmlrpc_datetime.lo \
+       xmlrpc_array.lo \
+       xmlrpc_struct.lo \
+       $(XMLRPC_XML_PARSER) \
+       xmlrpc_parse.lo \
+       xmlrpc_serialize.lo \
+       xmlrpc_base64.lo \
+       xmlrpc_utf8.lo \
+       xmlrpc_authcookie.lo \
+
+LIBXMLRPC_LIBDEP = -lxmlrpc_util $(LIBXML_LIBS)
+
+LIB_OBJS = $(LIBXMLRPC_CLIENT_OBJS) $(LIBXMLRPC_SERVER_OBJS)
+
+TRANSPORT_INCLUDES = \
+  -I$(WININET_TRANSPORT_DIR) \
+  -I$(CURL_TRANSPORT_DIR) \
+  -I$(LIBWWW_TRANSPORT_DIR) \
+
+INCLUDES = -I$(BUILDDIR) -I$(SRCDIR) \
+           -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
+          -I$(SRCDIR)/lib/abyss/src \
+          $(TRANSPORT_INCLUDES) \
+          $(LIBXML_INCLUDES) \
+
+# People sometimes think that when the Xmlrpc-c build has been
+# configured for no Abyss server (configure --disable-abyss), that
+# libmxlrpc_server_abyss should not get built.  But
+# libxmlrpc_server_abyss is not part of the Abyss server; it is merely
+# some code that exploits an Abyss server, and you don't need to have a
+# built Abyss server to build it.
+
+TARGET_LTLIBRARIES = libxmlrpc.la libxmlrpc_server.la \
+     libxmlrpc_server_abyss.la
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  TARGET_LTLIBRARIES += libxmlrpc_client.la
+endif
+
+ifeq ($(ENABLE_CGI_SERVER),yes)
+  TARGET_LTLIBRARIES += libxmlrpc_server_cgi.la
+endif
+
+all: $(TARGET_LTLIBRARIES) $(SUBDIRS:%=%/all)
+
+LDFLAGS = $(LADD)
+
+LIBPATHS = -L.libs -L$(LIBUTIL_LIBDIR)
+
+LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR) $(LIBPATHS) $(LADD)
+
+
+libxmlrpc.la: $(LIBXMLRPC_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) \
+         $(LIBXMLRPC_OBJS) $(LIBXMLRPC_LIBDEP) 
+
+libxmlrpc_client.la: $(LIBXMLRPC_CLIENT_OBJS) $(TRANSPORT_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) \
+         $(LIBXMLRPC_CLIENT_OBJS) $(TRANSPORT_OBJS) \
+         $(LIBXMLRPC_CLIENT_LIBDEP) $(TRANSPORT_LIBDEP) \
+
+libxmlrpc_server.la: $(LIBXMLRPC_SERVER_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) \
+         $(LIBXMLRPC_SERVER_OBJS) $(LIBXMLRPC_SERVER_LIBDEP)
+
+libxmlrpc_server_abyss.la: $(LIBXMLRPC_SERVER_ABYSS_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) \
+         $(LIBXMLRPC_SERVER_ABYSS_OBJS) $(LIBXMLRPC_SERVER_ABYSS_LIBDEP)
+
+libxmlrpc_server_cgi.la: $(LIBXMLRPC_SERVER_CGI_OBJS)
+       $(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) \
+         $(LIBXMLRPC_SERVER_CGI_OBJS) $(LIBXMLRPC_SERVER_CGI_LIBDEP)
+
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+$(LIBXMLRPC_CLIENT_OBJS) $(LIBXMLRPC_SERVER_OBJS):%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+$(LIBXMLRPC_OBJS):%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(LIBXML_INCLUDES) \
+         $(CFLAGS) $<
+
+$(LIBXMLRPC_SERVER_ABYSS_OBJS):%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(ABYSS_INCLUDES) \
+         $(CFLAGS) $<
+
+xmlrpc_server_cgi.lo:%.lo:%.c
+       $(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) \
+         $(CFLAGS) $<
+
+LTLIBRARIES_TO_INSTALL = $(TARGET_LTLIBRARIES)
+
+check:
+       $(MAKE) -C test runtests
+       $(MAKE) -C cpp  check
+
+.PHONY: install
+install: install-common $(SUBDIRS:%=%/install)
+
+.PHONY: clean clean-local distclean
+clean: clean-common clean-local $(SUBDIRS:%=%/clean)
+clean-local:
+       $(MAKE) -C test clean
+
+distclean: clean-common clean-local distclean-common $(SUBDIRS:%=%/distclean)
+
+.PHONY: dep
+dep: $(SUBDIRS:%=%/dep) $(BUILDDIR)/transport_config.h dep-common
+
+include $(SRCDIR)/Makefile.common
+
+xmlrpc_client.lo: $(BUILDDIR)/transport_config.h
+
+include Makefile.depend
diff --git a/src/Makefile.depend b/src/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/cpp/Makefile b/src/cpp/Makefile
new file mode 100644 (file)
index 0000000..35c8a34
--- /dev/null
@@ -0,0 +1,190 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR := $(CURDIR)/../..
+endif
+SUBDIR := src/cpp
+# BLDDIR is for use in places where a symbolic link won't work.
+# BUILDDIR is for places in Makefile.common that can use the 'blddir'
+# symbolic link (but in directories that don't, like this one, have
+# blddir, these places use something else -- hence the variable).
+BLDDIR = ../..
+BUILDDIR := blddir
+VPATH = .:$(SRCDIR)
+
+include $(BLDDIR)/Makefile.config
+
+default: all
+
+# libxmlrpc_cpp is the legacy C++ wrapper library.  The others are the
+# more elaborate replacements.
+
+TARGET_LIBRARY_NAMES := \
+  libxmlrpc_cpp \
+  libxmlrpc++ \
+  libxmlrpc_server++ \
+  libxmlrpc_server_abyss++ \
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  TARGET_LIBRARY_NAMES += libxmlrpc_client++
+endif
+
+STATIC_LIBRARIES_TO_INSTALL = $(TARGET_STATIC_LIBRARIES)
+
+SHARED_LIBS_TO_BUILD := $(TARGET_LIBRARY_NAMES)
+SHARED_LIBS_TO_INSTALL := $(TARGET_LIBRARY_NAMES)
+
+# INCLUDES and DEP_SOURCES are used by dep-common target
+INCLUDES = $(BASIC_INCLUDES) $(CLIENT_INCLUDES) $(LIBXML_INCLUDES) \
+  $(SERVER_INCLUDES) $(SERVER_ABYSS_INCLUDES) $(TRANSPORT_INCLUDES)
+DEP_SOURCES = *.cpp
+
+WININET_TRANSPORT_DIR = srcdir/lib/wininet_transport
+CURL_TRANSPORT_DIR    = srcdir/lib/curl_transport
+LIBWWW_TRANSPORT_DIR  = srcdir/lib/libwww_transport
+
+ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
+  LIBXML_INCLUDES = $(LIBXML2_CFLAGS)
+else
+  LIBXML_INCLUDES = -Isrcdir/lib/expat/xmlparse
+endif
+
+LIBXMLRPCPP_OBJS = \
+       base64.o \
+       env_wrap.o \
+       fault.o \
+       girerr.o \
+       girmem.o \
+       outcome.o \
+       param_list.o \
+       value.o \
+       xml.o \
+
+LIBXMLRPC_SERVERPP_OBJS = registry.o
+LIBXMLRPC_SERVER_ABYSSPP_OBJS = server_abyss.o
+LIBXMLRPC_CLIENTPP_OBJS = client.o client_simple.o curl.o libwww.o wininet.o
+
+ALL_OBJS = \
+  XmlRpcCpp.o \
+  $(LIBXMLRPCCPP_OBJS) \
+  $(LIBXMLRPC_SERVERPP_OBJS) \
+  $(LIBXMLRPC_SERVER_ABYSSPP_OBJS) \
+  $(LIBXMLRPC_CLIENTPP_OBJS)
+
+include $(SRCDIR)/Makefile.common
+
+# This 'Makefile.common' dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(SRCDIR)/Makefile.common: srcdir blddir
+
+TRANSPORT_INCLUDES = \
+  -I$(WININET_TRANSPORT_DIR) \
+  -I$(CURL_TRANSPORT_DIR) \
+  -I$(LIBWWW_TRANSPORT_DIR) \
+
+BASIC_INCLUDES = -Isrcdir/include -Iblddir -Isrcdir \
+  -Isrcdir/lib/util/include
+
+ifeq ($(SHARED_LIB_TYPE),unix)
+  include unix.make
+  endif
+
+ifeq ($(SHARED_LIB_TYPE),irix)
+  include irix.make
+  endif
+
+ifeq ($(SHARED_LIB_TYPE),dll)
+  include dll.make
+  endif
+
+ifeq ($(SHARED_LIB_TYPE),dylib)
+  include dylib.make
+  endif
+
+ifneq ($(SHARED_LIB_TYPE),NONE)
+  TARGET_SHARED_LIBRARIES = $(TARGET_LIBRARY_NAMES:%=%.$(SHLIB_SUFFIX))
+  endif
+
+TARGET_STATIC_LIBRARIES = $(TARGET_LIBRARY_NAMES:%=%.a)
+
+TARGET_LIBRARIES = $(TARGET_STATIC_LIBRARIES) $(ALL_SHARED_LIBRARIES)
+
+all: $(TARGET_LIBRARIES)
+
+libxmlrpc_cpp.a: XmlRpcCpp.o
+       -rm -f $@
+       $(AR) cru $@ $^
+       $(RANLIB) $@
+
+libxmlrpc++.a: $(LIBXMLRPCPP_OBJS)
+       -rm -f $@
+       $(AR) cru $@ $^
+       $(RANLIB) $@
+
+libxmlrpc_server++.a: $(LIBXMLRPC_SERVERPP_OBJS)
+       -rm -f $@
+       $(AR) cru $@ $^
+       $(RANLIB) $@
+
+libxmlrpc_server_abyss++.a: $(LIBXMLRPC_SERVER_ABYSSPP_OBJS)
+       -rm -f $@
+       $(AR) cru $@ $^
+       $(RANLIB) $@
+
+libxmlrpc_client++.a: $(LIBXMLRPC_CLIENTPP_OBJS)
+       -rm -f $@
+       $(AR) cru $@ $^
+       $(RANLIB) $@
+
+#-----------------------------------------------------------------------------
+#  RULES TO COMPILE OBJECT MODULES FOR LIBRARIES
+#-----------------------------------------------------------------------------
+
+CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+XmlRpcCpp.o:%.o:%.cpp
+       $(CXX) -c $(BASIC_INCLUDES) $(CXXFLAGS) $<
+
+$(LIBXMLRPCPP_OBJS):%.o:%.cpp
+       $(CXX) -c $(BASIC_INCLUDES) $(CXXFLAGS) $<
+
+SERVER_INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES)
+
+$(LIBXMLRPC_SERVERPP_OBJS):%.o:%.cpp
+       $(CXX) -c $(SERVER_INCLUDES) $(CXXFLAGS) $<
+
+SERVER_ABYSS_INCLUDES = $(SERVER_INCLUDES) -Isrcdir/lib/abyss/src
+
+$(LIBXMLRPC_SERVER_ABYSSPP_OBJS):%.o:%.cpp
+       $(CXX) -c $(SERVER_ABYSS_INCLUDES) $(CXXFLAGS) $<
+
+CLIENT_INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES) $(TRANSPORT_INCLUDES)
+
+$(LIBXMLRPC_CLIENTPP_OBJS):%.o:%.cpp
+       $(CXX) -c $(CLIENT_INCLUDES) $(CXXFLAGS) $<
+
+client.o curl.o libwww.o wininet.o: $(BUILDDIR)/transport_config.h
+
+#-----------------------------------------------------------------------------
+#  MISCELLANEOUS RULES
+#-----------------------------------------------------------------------------
+
+check:
+       $(MAKE) -C test runtests
+
+.PHONY: install
+install: install-common
+
+.PHONY: clean clean-local distclean distclean-local
+clean: clean-common clean-local
+clean-local:
+       $(MAKE) -C test clean
+
+distclean: clean distclean-local distclean-common
+
+distclean-local:
+       $(MAKE) -C test distclean
+
+.PHONY: dep
+dep: dep-common $(BUILDDIR)/transport_config.h
+
+include Makefile.depend
diff --git a/src/cpp/Makefile.depend b/src/cpp/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/cpp/XmlRpcCpp.cpp b/src/cpp/XmlRpcCpp.cpp
new file mode 100644 (file)
index 0000000..4226a2d
--- /dev/null
@@ -0,0 +1,395 @@
+// Copyright (C) 2001 by Eric Kidd. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. The name of the author may not be used to endorse or promote products
+//    derived from this software without specific prior written permission. 
+//  
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+
+
+#include <string>
+#include <cstring>
+
+#include "xmlrpc-c/oldcppwrapper.hpp"
+
+using std::string;
+
+//=========================================================================
+//  XmlRpcFault Methods
+//=========================================================================
+
+XmlRpcFault::XmlRpcFault (const XmlRpcFault &fault) {
+    xmlrpc_env_init(&mFault);
+    xmlrpc_env_set_fault(&mFault,
+                         fault.mFault.fault_code,
+                         fault.mFault.fault_string);
+}
+
+XmlRpcFault::XmlRpcFault (const int faultCode, const string faultString) {
+    xmlrpc_env_init(&mFault);
+    xmlrpc_env_set_fault(&mFault, faultCode,
+                         const_cast<char*>(faultString.c_str()));
+}
+XmlRpcFault::XmlRpcFault (const xmlrpc_env *env) {
+    if (!env->fault_string)
+        throw XmlRpcFault(XMLRPC_INTERNAL_ERROR,
+                          "Tried to create empty fault");
+    xmlrpc_env_init(&mFault);
+    xmlrpc_env_set_fault(&mFault, env->fault_code,
+                         const_cast<char*>(env->fault_string));
+}
+
+XmlRpcFault::~XmlRpcFault (void) {
+    xmlrpc_env_clean(&mFault);
+}
+
+string XmlRpcFault::getFaultString (void) const {
+    XMLRPC_ASSERT(mFault.fault_occurred);
+    return string(mFault.fault_string);
+}
+
+
+//=========================================================================
+//  XmlRpcEnv Methods
+//=========================================================================
+
+XmlRpcEnv::XmlRpcEnv (const XmlRpcEnv &env) {
+    xmlrpc_env_init(&mEnv);
+    if (env.hasFaultOccurred())
+        xmlrpc_env_set_fault(&mEnv,
+                             env.mEnv.fault_code,
+                             env.mEnv.fault_string);
+}
+
+XmlRpcFault XmlRpcEnv::getFault (void) const {
+    return XmlRpcFault(&mEnv);
+}
+
+void XmlRpcEnv::throwMe (void) const {
+    throw XmlRpcFault(&mEnv);
+}
+
+
+//=========================================================================
+//  XmlRpcValue Methods
+//=========================================================================
+
+// If the user doesn't tell us what kind of value to create, use
+// a false boolean value as the default.
+XmlRpcValue::XmlRpcValue (void) {
+    XmlRpcEnv env;
+    mValue = xmlrpc_build_value(env, "b", (xmlrpc_bool) 0);
+    env.throwIfFaultOccurred();
+}
+
+XmlRpcValue XmlRpcValue::makeInt (const XmlRpcValue::int32 i) {
+    XmlRpcEnv env;
+    xmlrpc_value *value = xmlrpc_build_value(env, "i", i);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);
+}
+
+XmlRpcValue XmlRpcValue::makeBool (const bool b) {
+    XmlRpcEnv env;
+    xmlrpc_value *value = xmlrpc_build_value(env, "b", (xmlrpc_bool) b);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);
+}
+
+XmlRpcValue XmlRpcValue::makeDouble (const double d) {
+    XmlRpcEnv env;
+    xmlrpc_value *value = xmlrpc_build_value(env, "d", d);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);
+}
+
+XmlRpcValue XmlRpcValue::makeDateTime (const string& dateTime) {
+    XmlRpcEnv env;
+    xmlrpc_value *value;
+    const char *data = dateTime.c_str(); // Make sure we're not using wchar_t.
+    value = xmlrpc_build_value(env, "8", data);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);    
+}
+
+XmlRpcValue XmlRpcValue::makeString (const string& str) {
+    XmlRpcEnv env;
+    const char *data = str.data();      // Make sure we're not using wchar_t.
+    size_t size = str.size();
+    xmlrpc_value *value = xmlrpc_build_value(env, "s#", data, size);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);    
+}
+
+XmlRpcValue XmlRpcValue::makeString (const char *const str) {
+    XmlRpcEnv env;
+    xmlrpc_value *value = xmlrpc_build_value(env, "s", str);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);    
+}
+
+XmlRpcValue XmlRpcValue::makeString (const char *const str, size_t len) {
+    XmlRpcEnv env;
+    xmlrpc_value *value = xmlrpc_build_value(env, "s#", str, len);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);    
+}
+
+XmlRpcValue XmlRpcValue::makeArray (void) {
+    XmlRpcEnv env;
+    xmlrpc_value *value = xmlrpc_build_value(env, "()");
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);    
+}
+
+XmlRpcValue XmlRpcValue::makeStruct (void) {
+    XmlRpcEnv env;
+    xmlrpc_value *value = xmlrpc_struct_new(env);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);
+}
+
+XmlRpcValue XmlRpcValue::makeBase64 (const unsigned char *const data,
+                                     size_t len)
+{
+    XmlRpcEnv env;
+    xmlrpc_value *value = xmlrpc_build_value(env, "6", data, len);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(value, CONSUME_REFERENCE);
+}
+
+XmlRpcValue::int32 XmlRpcValue::getInt (void) const {
+    XmlRpcEnv env;
+    XmlRpcValue::int32 result;
+    xmlrpc_parse_value(env, mValue, "i", &result);
+    env.throwIfFaultOccurred();
+    return result;
+}
+
+bool XmlRpcValue::getBool (void) const {
+    XmlRpcEnv env;
+    xmlrpc_bool result;
+    xmlrpc_parse_value(env, mValue, "b", &result);
+    env.throwIfFaultOccurred();
+    return result;
+}
+
+double XmlRpcValue::getDouble (void) const {
+    XmlRpcEnv env;
+    double result;
+    xmlrpc_parse_value(env, mValue, "d", &result);
+    env.throwIfFaultOccurred();
+    return result;
+}
+
+string XmlRpcValue::getRawDateTime (void) const {
+    XmlRpcEnv env;
+    char *result;
+    xmlrpc_parse_value(env, mValue, "8", &result);
+    env.throwIfFaultOccurred();
+    return string(result);
+}
+
+string XmlRpcValue::getString (void) const {
+    XmlRpcEnv env;
+    char *result;
+    size_t result_len;
+    xmlrpc_parse_value(env, mValue, "s#", &result, &result_len);
+    env.throwIfFaultOccurred();
+    return string(result, result_len);
+    
+}
+
+XmlRpcValue XmlRpcValue::getArray (void) const {
+    XmlRpcEnv env;
+    xmlrpc_value *result;
+    xmlrpc_parse_value(env, mValue, "A", &result);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(result);
+}
+
+XmlRpcValue XmlRpcValue::getStruct (void) const {
+    XmlRpcEnv env;
+    xmlrpc_value *result;
+    xmlrpc_parse_value(env, mValue, "S", &result);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(result);
+}
+
+void XmlRpcValue::getBase64 (const unsigned char *& out_data,
+                             size_t& out_len) const
+{
+    XmlRpcEnv env;
+    xmlrpc_parse_value(env, mValue, "6", &out_data, &out_len);
+    env.throwIfFaultOccurred();
+}
+
+size_t XmlRpcValue::arraySize (void) const {
+    XmlRpcEnv env;
+    size_t result = xmlrpc_array_size(env, mValue);
+    env.throwIfFaultOccurred();
+    return result;
+}
+
+void XmlRpcValue::arrayAppendItem (const XmlRpcValue& value) {
+    XmlRpcEnv env;
+    xmlrpc_array_append_item(env, mValue, value.borrowReference());
+    env.throwIfFaultOccurred();
+}
+
+XmlRpcValue XmlRpcValue::arrayGetItem (int index) const {
+    XmlRpcEnv env;
+    xmlrpc_value *result = xmlrpc_array_get_item(env, mValue, index);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(result);
+}
+
+size_t XmlRpcValue::structSize (void) const {
+    XmlRpcEnv env;
+    size_t result = xmlrpc_struct_size(env, mValue);
+    env.throwIfFaultOccurred();
+    return result;
+}
+
+bool XmlRpcValue::structHasKey (const string& key) const {
+    XmlRpcEnv env;
+    const char *keystr = key.data();
+    size_t keylen = key.size();
+    bool result = xmlrpc_struct_has_key_n(env, mValue,
+                                          const_cast<char*>(keystr), keylen);
+    env.throwIfFaultOccurred();
+    return result;
+}
+
+XmlRpcValue XmlRpcValue::structGetValue (const string& key) const {
+    XmlRpcEnv env;
+    const char *keystr = key.data();
+    size_t keylen = key.size();
+    xmlrpc_value *result =
+        xmlrpc_struct_get_value_n(env, mValue,
+                                  const_cast<char*>(keystr), keylen);
+    env.throwIfFaultOccurred();
+    return XmlRpcValue(result);
+}
+
+void XmlRpcValue::structSetValue (const string& key, const XmlRpcValue& value)
+{
+    XmlRpcEnv env;
+    const char *keystr = key.data();
+    size_t keylen = key.size();
+    xmlrpc_struct_set_value_n(env, mValue, (char*) keystr, keylen,
+                              value.borrowReference());
+    env.throwIfFaultOccurred();
+}
+
+void XmlRpcValue::structGetKeyAndValue (const int index,
+                                        string& out_key,
+                                        XmlRpcValue& out_value) const
+{
+    XmlRpcEnv env;
+
+    xmlrpc_value *key, *value;
+    xmlrpc_struct_get_key_and_value(env, mValue, index, &key, &value);
+    env.throwIfFaultOccurred();
+
+    out_key = XmlRpcValue(key).getString();
+    out_value = XmlRpcValue(value);
+}
+
+XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
+                                       xmlrpc_method method,
+                                       void *data)
+{
+    XmlRpcEnv env;
+
+    xmlrpc_registry_add_method (env, mRegistry, NULL,
+                                name.c_str (),
+                                method, data);
+
+    env.throwIfFaultOccurred ();
+    return (*this);
+}
+
+XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
+                                       xmlrpc_method method,
+                                       void* data,
+                                       const string& signature,
+                                       const string& help)
+{
+    XmlRpcEnv env;
+
+    xmlrpc_registry_add_method_w_doc (env, mRegistry, NULL,
+                                      name.c_str (),
+                                      method, data,
+                                      signature.c_str (),
+                                      help.c_str ());
+
+    env.throwIfFaultOccurred ();
+    return (*this);
+}
+
+xmlrpc_mem_block* XmlRpcGenSrv::alloc (XmlRpcEnv& env, const string& body) const
+{
+    xmlrpc_mem_block*   result = NULL;
+    char*               contents;
+
+    result      = xmlrpc_mem_block_new (env, body.length ());
+    env.throwIfFaultOccurred ();
+
+    contents    = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, result);
+
+    memcpy (contents, body.c_str (), body.length ());
+    return result;
+}
+
+string XmlRpcGenSrv::handle (const string& body) const
+{
+    XmlRpcEnv env;
+    string result;
+    xmlrpc_mem_block*   input = NULL, * output = NULL; 
+    char* input_data, * output_data;
+    size_t input_size, output_size;
+
+    if (body.length () > xmlrpc_limit_get (XMLRPC_XML_SIZE_LIMIT_ID))
+        throw XmlRpcFault (XMLRPC_LIMIT_EXCEEDED_ERROR, "XML-RPC request too large");
+
+    input   = alloc (env, body);
+    input_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, input);
+    input_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input);
+
+    output  = xmlrpc_registry_process_call (env, mRegistry, NULL,
+                                            input_data, input_size);
+
+    if (output)
+    {
+        output_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output);
+        output_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+
+        result.assign (output_data, output_size);
+        xmlrpc_mem_block_free (output);
+    }
+
+    xmlrpc_mem_block_free (input);
+    if (!result.length ())
+        throw XmlRpcFault (env);
+
+    return result;
+}
diff --git a/src/cpp/base64.cpp b/src/cpp/base64.cpp
new file mode 100644 (file)
index 0000000..f9c0dac
--- /dev/null
@@ -0,0 +1,234 @@
+#include <cassert>
+#include <string>
+#include <vector>
+#include <bitset>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base64.hpp"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+char const table_a2b_base64[] = {
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+    52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, /* Note PAD->0 */
+    -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
+    15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+    -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+    41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+};
+
+char const base64Pad('=');
+size_t const base64MaxChunkSize(57);
+     // Max binary chunk size (76 character line)
+#define BASE64_LINE_SZ 128      /* Buffer size for a single line. */    
+
+unsigned char const table_b2a_base64[] =
+   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+} // namespace
+
+
+
+class bitBuffer {
+public:
+    bitBuffer() : bitsInBuffer(0) {};
+
+    void
+    shiftIn8Bits(unsigned char const newBits) {
+        // Shift in 8 bits to the right end of the buffer
+
+        this->buffer = (this->buffer << 8) | newBits;
+        this->bitsInBuffer += 8;
+
+        assert(this->bitsInBuffer <= 12);
+    }
+
+    void
+    shiftIn6Bits(unsigned char const newBits) {
+        // Shift in 6 bits to the right end of the buffer
+
+        this->buffer = (this->buffer << 6) | newBits;
+        this->bitsInBuffer += 6;
+
+        assert(this->bitsInBuffer <= 12);
+    }
+
+    void
+    shiftOut6Bits(unsigned char * const outputP) {
+        // Shift out 6 bits from the left end of the buffer
+
+        assert(bitsInBuffer >= 6);
+
+        *outputP = (this->buffer >> (this->bitsInBuffer - 6)) & 0x3f;
+        this->bitsInBuffer -= 6;
+    }
+
+    void
+    shiftOut8Bits(unsigned char * const outputP) {
+        // Shift out 8 bits from the left end of the buffer
+
+        assert(bitsInBuffer >= 8);
+
+        *outputP = (this->buffer >> (this->bitsInBuffer - 8)) & 0x3f;
+        this->bitsInBuffer -= 8;
+    }
+
+    void
+    shiftOutResidue(unsigned char * const outputP) {
+        // Shift out the residual 2 or 4 bits, padded on the right with 0
+        // to 6 bits.
+
+        while (this->bitsInBuffer < 6) {
+            this->buffer <<= 2;
+            this->bitsInBuffer += 2;
+        }
+        
+        this->shiftOut6Bits(outputP);
+    }
+
+    void
+    discardResidue() {
+        assert(bitsInBuffer < 8);
+        
+        this->bitsInBuffer = 0;
+    }
+    
+    unsigned int
+    bitCount() {
+        return bitsInBuffer;
+    }
+
+private:
+    unsigned int buffer;
+    unsigned int bitsInBuffer;
+};
+
+
+namespace xmlrpc_c {
+
+
+static void
+encodeChunk(vector<unsigned char> const& bytes,
+            size_t                const  lineStart,
+            size_t                const  chunkSize,
+            string *              const  outputP) {
+    
+    bitBuffer buffer;
+        // A buffer in which we accumulate bits (up to 12 bits)
+        // until we have enough (6) for a base64 character.
+
+    // I suppose this would be more efficient with an iterator on
+    // 'bytes' and/or *outputP.  I'd have to find out how to use one.
+
+    for (size_t linePos = 0; linePos < chunkSize; ++linePos) {
+        // Shift the data into our buffer
+        buffer.shiftIn8Bits(bytes[lineStart + linePos]);
+        
+        // Encode any complete 6 bit groups
+        while (buffer.bitCount() >= 6) {
+            unsigned char theseBits;
+            buffer.shiftOut6Bits(&theseBits);
+            outputP->append(1, table_b2a_base64[theseBits]);
+        }
+    }
+    if (buffer.bitCount() > 0) {
+        // Handle residual bits in the buffer
+        unsigned char theseBits;
+        buffer.shiftOutResidue(&theseBits);
+    
+        outputP->append(1, table_b2a_base64[theseBits]);
+
+        // Pad to a multiple of 4 characters (24 bits)
+        assert(outputP->length() % 4 > 0);
+        outputP->append(4-outputP->length() % 4, base64Pad);
+    } else {
+        assert(outputP->length() % 4 == 0);
+    }
+}
+
+
+
+string
+base64FromBytes(vector<unsigned char> const& bytes,
+                newlineCtl            const  newlineCtl) {
+
+    string retval;
+
+    if (bytes.size() == 0) {
+        if (newlineCtl == NEWLINE_YES)
+            retval = "\r\n";
+        else
+            retval = "";
+    } else {
+        // It would be good to preallocate retval.  Need to look up
+        // how to do that.
+        for (size_t chunkStart = 0;
+             chunkStart < bytes.size();
+             chunkStart += base64MaxChunkSize) {
+
+            size_t const chunkSize(
+                min(base64MaxChunkSize, bytes.size() - chunkStart));
+    
+            encodeChunk(bytes, chunkStart, chunkSize, &retval);
+
+            if (newlineCtl == NEWLINE_YES)
+                // Append a courtesy crlf
+                retval += "\r\n";
+        }
+    }
+    return retval;
+}
+
+
+
+vector<unsigned char>
+bytesFromBase64(string const& base64) {
+
+    vector<unsigned char> retval;
+    bitBuffer buffer;
+    unsigned int npad;
+
+    npad = 0;  // No pad characters seen yet
+
+    for (unsigned int cursor = 0; cursor < base64.length(); ++cursor) {
+        char const thisChar(base64[cursor] & 0x7f);
+
+        if (thisChar == '\r' || thisChar == '\n' || thisChar == ' ') {
+            // ignore this punctuation
+        } else {
+            if (thisChar == base64Pad) {
+                // This pad character is here to synchronize a chunk to 
+                // a multiple of 24 bits (4 base64 characters; 3 bytes).
+                buffer.discardResidue();
+            } else {
+                unsigned int const tableIndex(thisChar);
+                if (table_a2b_base64[tableIndex] == -1)
+                    throwf("Contains non-base64 character "
+                           "with ASCII code 0x%02x", thisChar);
+                
+                buffer.shiftIn6Bits(table_a2b_base64[tableIndex]);
+            
+                if (buffer.bitCount() >= 8) {
+                    unsigned char thisByte;
+                    buffer.shiftOut8Bits(&thisByte);
+                    retval.push_back(thisByte);
+                }
+            }
+        }
+    }
+
+    if (buffer.bitCount() > 0)
+        throwf("Not a multiple of 4 characters");
+
+    return retval;
+}
+
+} //namespace
diff --git a/src/cpp/client.cpp b/src/cpp/client.cpp
new file mode 100644 (file)
index 0000000..50d8695
--- /dev/null
@@ -0,0 +1,962 @@
+/*=============================================================================
+                                client.cpp
+===============================================================================
+  This is the C++ XML-RPC client library for Xmlrpc-c.
+
+  Note that unlike most of Xmlprc-c's C++ API, this is _not_ based on the
+  C client library.  This code is independent of the C client library, and
+  is based directly on the client XML transport libraries (with a little
+  help from internal C utility libraries).
+=============================================================================*/
+
+#include <stdlib.h>
+#include <cassert>
+#include <string>
+#include <vector>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/girmem.hpp"
+using girmem::autoObjectPtr;
+using girmem::autoObject;
+#include "env_wrap.hpp"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/transport.h"
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/xml.hpp"
+#include "xmlrpc-c/client.hpp"
+#include "transport_config.h"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+void
+throwIfError(env_wrap const& env) {
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+}
+
+
+
+class memblockStringWrapper {
+
+public:    
+    memblockStringWrapper(string const value) {
+
+        env_wrap env;
+
+        this->memblockP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0);
+        throwIfError(env);
+
+        XMLRPC_MEMBLOCK_APPEND(char, &env.env_c, this->memblockP,
+                               value.c_str(), value.size());
+        throwIfError(env);
+    }
+    
+    memblockStringWrapper(xmlrpc_mem_block * const memblockP) :
+        memblockP(memblockP) {};
+
+    ~memblockStringWrapper() {
+        XMLRPC_MEMBLOCK_FREE(char, this->memblockP);
+    }
+
+    xmlrpc_mem_block * memblockP;
+};
+
+} // namespace
+
+namespace xmlrpc_c {
+
+carriageParm::carriageParm() {}
+
+
+
+carriageParm::~carriageParm() {}
+
+
+
+carriageParmPtr::carriageParmPtr() {
+    // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParmPtr::carriageParmPtr(
+    carriageParm * const carriageParmP) {
+    this->point(carriageParmP);
+}
+
+
+
+carriageParm *
+carriageParmPtr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<carriageParm *>(p);
+}
+
+
+
+carriageParm *
+carriageParmPtr::get() const {
+    return dynamic_cast<carriageParm *>(objectP);
+}
+
+
+
+carriageParm_http0::carriageParm_http0() :
+    c_serverInfoP(NULL) {}
+
+
+
+carriageParm_http0::carriageParm_http0(string const serverUrl) {
+    this->c_serverInfoP = NULL;
+
+    this->instantiate(serverUrl);
+}
+
+
+
+carriageParm_http0::~carriageParm_http0() {
+
+    if (this->c_serverInfoP)
+        xmlrpc_server_info_free(this->c_serverInfoP);
+}
+
+
+
+void
+carriageParm_http0::instantiate(string const serverUrl) {
+
+    if (c_serverInfoP)
+        throw(error("object already instantiated"));
+    
+    env_wrap env;
+
+    this->c_serverInfoP =
+        xmlrpc_server_info_new(&env.env_c, serverUrl.c_str());
+    throwIfError(env);
+}
+
+
+
+void
+carriageParm_http0::setBasicAuth(string const username,
+                                 string const password) {
+
+    if (!c_serverInfoP)
+        throw(error("object not instantiated"));
+    
+    env_wrap env;
+
+    xmlrpc_server_info_set_basic_auth(
+        &env.env_c, this->c_serverInfoP, username.c_str(), password.c_str());
+    throwIfError(env);
+}
+
+
+
+carriageParm_http0Ptr::carriageParm_http0Ptr() {
+    // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParm_http0Ptr::carriageParm_http0Ptr(
+    carriageParm_http0 * const carriageParmP) {
+    this->point(carriageParmP);
+}
+
+
+
+carriageParm_http0 *
+carriageParm_http0Ptr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<carriageParm_http0 *>(p);
+}
+
+
+
+xmlTransaction::xmlTransaction() {}
+
+
+
+void
+xmlTransaction::finish(string const& responseXml) const {
+
+    xml::trace("XML-RPC RESPONSE", responseXml);
+}
+
+
+
+void
+xmlTransaction::finishErr(error const&) const {
+
+}
+
+
+
+xmlTransactionPtr::xmlTransactionPtr() {}
+
+
+
+xmlTransaction *
+xmlTransactionPtr::operator->() const {
+    autoObject * const p(this->objectP);
+    return dynamic_cast<xmlTransaction *>(p);
+}
+
+
+
+struct xmlTranCtl {
+/*----------------------------------------------------------------------------
+   This contains information needed to conduct a transaction.  You
+   construct it as you start the transaction and destroy it after the
+   work is done.  You need this only for an asynchronous one, because
+   where the user starts and finishes the RPC in the same
+   libxmlrpc_client call, you can just keep this information in
+   various stack variables, and it's faster and easier to understand
+   that way.
+
+   The C transport is designed to take a xmlrpc_call_info argument for
+   similar stuff needed by the the C client object.  But it's really
+   opaque to the transport, so we just let xmlTranCtl masquerade as
+   xmlprc_call_info in our call to the C transport.
+-----------------------------------------------------------------------------*/
+    xmlTranCtl(xmlTransactionPtr const& xmlTranP,
+               string            const& callXml) :
+
+        xmlTranP(xmlTranP) {
+
+        env_wrap env;
+
+        this->callXmlP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0);
+        throwIfError(env);
+
+        XMLRPC_MEMBLOCK_APPEND(char, &env.env_c, this->callXmlP,
+                               callXml.c_str(), callXml.size());
+        throwIfError(env);
+    }
+    
+    ~xmlTranCtl() {
+        XMLRPC_MEMBLOCK_FREE(char, this->callXmlP);
+    }
+
+    xmlTransactionPtr const xmlTranP;
+        // The transaction we're controlling.  Most notable use of this is
+        // that this object we inform when the transaction is done.  This
+        // is where the response XML and other transaction results go.
+
+    xmlrpc_mem_block * callXmlP;
+        // The XML of the call.  This is what the transport transports.
+};
+
+
+
+clientXmlTransport::~clientXmlTransport() {}
+
+
+
+void
+clientXmlTransport::start(carriageParm *    const  carriageParmP,
+                          string            const& callXml,
+                          xmlTransactionPtr const& xmlTranP) {
+    
+    string responseXml;
+
+    this->call(carriageParmP, callXml, &responseXml);
+
+    xmlTranP->finish(responseXml);
+}
+
+
+
+void
+clientXmlTransport::finishAsync(xmlrpc_c::timeout const timeout) {
+    if (timeout.finite == timeout.finite)
+        throw(error("This class does not have finishAsync()"));
+}
+
+
+
+void
+clientXmlTransport::asyncComplete(
+    struct xmlrpc_call_info * const callInfoP,
+    xmlrpc_mem_block *        const responseXmlMP,
+    xmlrpc_env                const transportEnv) {
+
+    xmlTranCtl * const xmlTranCtlP = reinterpret_cast<xmlTranCtl *>(callInfoP);
+
+    try {
+        if (transportEnv.fault_occurred) {
+            xmlTranCtlP->xmlTranP->finishErr(error(transportEnv.fault_string));
+        } else {
+            string const responseXml(
+                XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlMP),
+                XMLRPC_MEMBLOCK_SIZE(char, responseXmlMP));
+            xmlTranCtlP->xmlTranP->finish(responseXml);
+        }
+    } catch(error) {
+        /* We can't throw an error back to C code, and the async_complete
+           interface does not provide for failure, so we define ->finish()
+           as not being capable of throwing an error.
+        */
+        assert(false);
+    }
+    delete(xmlTranCtlP);
+
+    /* Ordinarily, *xmlTranCtlP is the last reference to
+       xmlTranCtlP->xmlTranP, so that will get destroyed too.  But
+       ->finish() could conceivably create a new reference to
+       xmlTranCtlP->xmlTranP, and then it would keep living.
+    */
+}
+
+
+
+clientXmlTransportPtr::clientXmlTransportPtr() {
+    // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+clientXmlTransportPtr::clientXmlTransportPtr(
+    clientXmlTransport * const transportP) {
+    this->point(transportP);
+}
+
+
+
+clientXmlTransport *
+clientXmlTransportPtr::get() const {
+    return dynamic_cast<clientXmlTransport *>(objectP);
+}
+
+
+
+clientXmlTransport *
+clientXmlTransportPtr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<clientXmlTransport *>(p);
+}
+
+
+
+clientXmlTransport_http::~clientXmlTransport_http() {}
+
+
+
+void
+clientXmlTransport_http::call(
+    carriageParm * const  carriageParmP,
+    string         const& callXml,
+    string *       const  responseXmlP) {
+
+    carriageParm_http0 * const carriageParmHttpP =
+        dynamic_cast<carriageParm_http0 *>(carriageParmP);
+
+    if (carriageParmHttpP == NULL)
+        throw(error("HTTP client XML transport called with carriage "
+                    "parameter object not of class carriageParm_http"));
+
+    memblockStringWrapper callXmlM(callXml);
+
+    xmlrpc_mem_block * responseXmlMP;
+
+    env_wrap env;
+
+    this->c_transportOpsP->call(&env.env_c,
+                                this->c_transportP,
+                                carriageParmHttpP->c_serverInfoP,
+                                callXmlM.memblockP,
+                                &responseXmlMP);
+
+    throwIfError(env);
+
+    memblockStringWrapper responseHolder(responseXmlMP);
+        // Makes responseXmlMP get freed at end of scope
+    
+    *responseXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlMP),
+                           XMLRPC_MEMBLOCK_SIZE(char, responseXmlMP));
+}
+
+
+
+void
+clientXmlTransport_http::start(
+    carriageParm *    const  carriageParmP,
+    string            const& callXml,
+    xmlTransactionPtr const& xmlTranP) {
+
+    env_wrap env;
+
+    carriageParm_http0 * const carriageParmHttpP =
+        dynamic_cast<carriageParm_http0 *>(carriageParmP);
+
+    if (carriageParmHttpP == NULL)
+        throw(error("HTTP client XML transport called with carriage "
+                    "parameter object not of type carriageParm_http"));
+
+    xmlTranCtl * const tranCtlP(new xmlTranCtl(xmlTranP, callXml));
+
+    try {
+        this->c_transportOpsP->send_request(
+            &env.env_c,
+            this->c_transportP,
+            carriageParmHttpP->c_serverInfoP,
+            tranCtlP->callXmlP,
+            &this->asyncComplete,
+            reinterpret_cast<xmlrpc_call_info *>(tranCtlP));
+
+        throwIfError(env);
+    } catch (...) {
+        delete tranCtlP;
+        throw;
+    }
+}
+
+
+
+void
+clientXmlTransport_http::finishAsync(xmlrpc_c::timeout const timeout) {
+
+    xmlrpc_timeoutType const c_timeoutType(
+        timeout.finite ? timeout_yes : timeout_no);
+    xmlrpc_timeout const c_timeout(timeout.duration);
+
+    this->c_transportOpsP->finish_asynch(
+        this->c_transportP, c_timeoutType, c_timeout);
+}
+
+
+bool const haveCurl(
+#if MUST_BUILD_CURL_CLIENT
+true
+#else
+false
+#endif
+);
+
+bool const haveLibwww(
+#if MUST_BUILD_LIBWWW_CLIENT
+true
+#else
+false
+#endif
+);
+
+bool const haveWininet(
+#if MUST_BUILD_WININET_CLIENT
+true
+#else
+false
+#endif
+);
+
+
+
+vector<string>
+clientXmlTransport_http::availableTypes() {
+
+    vector<string> retval;
+
+    if (haveCurl)
+        retval.push_back("curl");
+
+    if (haveLibwww)
+        retval.push_back("libwww");
+
+    if (haveWininet)
+        retval.push_back("wininet");
+
+    return retval;
+}
+
+
+
+clientXmlTransportPtr
+clientXmlTransport_http::create() {
+/*----------------------------------------------------------------------------
+  Make an HTTP Client XML transport of any kind (Caller doesn't care).
+
+  Caller can find out what kind he got by trying dynamic casts.
+
+  Caller can use a carriageParm_http0 with the transport.
+-----------------------------------------------------------------------------*/
+    if (haveCurl)
+        return clientXmlTransportPtr(new clientXmlTransport_curl());
+    else if (haveLibwww)
+        return clientXmlTransportPtr(new clientXmlTransport_libwww());
+    else if (haveWininet)
+        return clientXmlTransportPtr(new clientXmlTransport_wininet());
+    else
+        throwf("This XML-RPC client library contains no HTTP XML transports");
+}
+
+
+
+clientTransaction::clientTransaction() {}
+
+
+
+clientTransactionPtr::clientTransactionPtr() {}
+
+
+
+clientTransactionPtr::~clientTransactionPtr() {}
+
+
+
+clientTransaction *
+clientTransactionPtr::operator->() const {
+    autoObject * const p(this->objectP);
+    return dynamic_cast<clientTransaction *>(p);
+}
+
+
+
+client::~client() {}
+
+
+
+void
+client::start(carriageParm *       const  carriageParmP,
+              string               const& methodName,
+              paramList            const& paramList,
+              clientTransactionPtr const& tranP) {
+/*----------------------------------------------------------------------------
+   Start an RPC, wait for it to complete, and finish it.
+
+   Usually, a derived class overrides this with something that does
+   not wait for the RPC to complete, but rather arranges for something
+   to finish the RPC later when the RPC does complete.
+-----------------------------------------------------------------------------*/
+    rpcOutcome outcome;
+
+    this->call(carriageParmP, methodName, paramList, &outcome);
+
+    tranP->finish(outcome);
+}
+
+
+
+clientPtr::clientPtr() {
+    // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+clientPtr::clientPtr(
+    client * const clientP) {
+    this->point(clientP);
+}
+
+
+
+client *
+clientPtr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<client *>(p);
+}
+
+
+
+client *
+clientPtr::get() const {
+    return dynamic_cast<client *>(objectP);
+}
+
+
+
+client_xml::client_xml(clientXmlTransport * const transportP) :
+    transportP(transportP) {}
+
+
+
+client_xml::client_xml(clientXmlTransportPtr const transportPtr) {
+
+    this->transportPtr = transportPtr;
+    this->transportP   = transportPtr.get();
+}
+     
+
+
+void
+client_xml::call(carriageParm * const  carriageParmP,
+                 string         const& methodName,
+                 paramList      const& paramList,
+                 rpcOutcome *   const  outcomeP) {
+
+    string callXml;
+    string responseXml;
+
+    xml::generateCall(methodName, paramList, &callXml);
+    
+    xml::trace("XML-RPC CALL", callXml);
+
+    try {
+        this->transportP->call(carriageParmP, callXml, &responseXml);
+    } catch (error const& error) {
+        throwf("Unable to transport XML to server and "
+               "get XML response back.  %s", error.what());
+    }
+    xml::trace("XML-RPC RESPONSE", responseXml);
+        
+    try {
+        xml::parseResponse(responseXml, outcomeP);
+    } catch (error const& error) {
+        throwf("Response XML from server is not valid XML-RPC response.  %s",
+               error.what());
+    }
+}
+
+
+void
+client_xml::start(carriageParm *       const  carriageParmP,
+                  string               const& methodName,
+                  paramList            const& paramList,
+                  clientTransactionPtr const& tranP) {
+
+    string callXml;
+
+    xml::generateCall(methodName, paramList, &callXml);
+    
+    xml::trace("XML-RPC CALL", callXml);
+
+    xmlTransaction_clientPtr const xmlTranP(tranP);
+
+    this->transportP->start(carriageParmP, callXml, xmlTranP);
+}
+
+
+void
+client_xml::finishAsync(xmlrpc_c::timeout const timeout) {
+
+    transportP->finishAsync(timeout);
+}
+
+
+
+serverAccessor::serverAccessor(clientPtr       const clientP,
+                               carriageParmPtr const carriageParmP) :
+
+    clientP(clientP), carriageParmP(carriageParmP) {};
+
+
+
+void
+serverAccessor::call(std::string            const& methodName,
+                     xmlrpc_c::paramList    const& paramList,
+                     xmlrpc_c::rpcOutcome * const  outcomeP) const {
+
+    this->clientP->call(this->carriageParmP.get(),
+                        methodName,
+                        paramList,
+                        outcomeP);
+}
+
+
+
+serverAccessorPtr::serverAccessorPtr() {
+    // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+serverAccessorPtr::serverAccessorPtr(
+    serverAccessor * const serverAccessorParmP) {
+    this->point(serverAccessorParmP);
+}
+
+
+
+serverAccessor *
+serverAccessorPtr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<serverAccessor *>(p);
+}
+
+
+
+serverAccessor *
+serverAccessorPtr::get() const {
+    return dynamic_cast<serverAccessor *>(objectP);
+}
+
+
+
+connection::connection(client *       const clientP,
+                       carriageParm * const carriageParmP) :
+    clientP(clientP), carriageParmP(carriageParmP) {}
+
+
+
+connection::~connection() {}
+
+
+
+rpc::rpc(string              const  methodName,
+         xmlrpc_c::paramList const& paramList) {
+    
+    this->state      = STATE_UNFINISHED;
+    this->methodName = methodName;
+    this->paramList  = paramList;
+}
+
+
+
+rpc::~rpc() {
+
+    if (this->state == STATE_ERROR)
+        delete(this->errorP);
+}
+
+
+
+void
+rpc::call(client       * const clientP,
+          carriageParm * const carriageParmP) {
+
+    if (this->state != STATE_UNFINISHED)
+        throw(error("Attempt to execute an RPC that has already been "
+                    "executed"));
+
+    clientP->call(carriageParmP,
+                  this->methodName,
+                  this->paramList,
+                  &this->outcome);
+
+    this->state = outcome.succeeded() ? STATE_SUCCEEDED : STATE_FAILED;
+}
+
+
+
+void
+rpc::call(connection const& connection) {
+
+    this->call(connection.clientP, connection.carriageParmP);
+
+}
+
+
+void
+rpc::start(client       * const clientP,
+           carriageParm * const carriageParmP) {
+    
+    if (this->state != STATE_UNFINISHED)
+        throw(error("Attempt to execute an RPC that has already been "
+                    "executed"));
+
+    clientP->start(carriageParmP,
+                   this->methodName,
+                   this->paramList,
+                   rpcPtr(this));
+}
+
+
+void
+rpc::start(xmlrpc_c::connection const& connection) {
+    
+    this->start(connection.clientP, connection.carriageParmP);
+}
+
+
+
+void
+rpc::finish(rpcOutcome const& outcome) {
+
+    this->state = outcome.succeeded() ? STATE_SUCCEEDED : STATE_FAILED;
+
+    this->outcome = outcome;
+
+    this->notifyComplete();
+}
+
+
+
+void
+rpc::finishErr(error const& error) {
+
+    this->state = STATE_ERROR;
+    this->errorP = new girerr::error(error);
+    this->notifyComplete();
+}
+
+
+
+void
+rpc::notifyComplete() {
+/*----------------------------------------------------------------------------
+   Anyone who does RPCs asynchronously and doesn't use polling will
+   want to make his own class derived from 'rpc' and override this
+   with a notifyFinish() that does something.
+
+   Typically, notifyFinish() will queue the RPC so some other thread
+   will deal with the fact that the RPC is finished.
+
+
+   In the absence of the aforementioned queueing, the RPC becomes
+   unreferenced as soon as our Caller releases his reference, so the
+   RPC gets destroyed when we return.
+-----------------------------------------------------------------------------*/
+
+}
+
+    
+
+value
+rpc::getResult() const {
+
+    switch (this->state) {
+    case STATE_UNFINISHED:
+        throw(error("Attempt to get result of RPC that is not finished."));
+        break;
+    case STATE_ERROR:
+        throw(*this->errorP);
+        break;
+    case STATE_FAILED:
+        throw(error("RPC response indicates failure.  " +
+                    this->outcome.getFault().getDescription()));
+        break;
+    case STATE_SUCCEEDED: {
+        // All normal
+    }
+    }
+
+    return this->outcome.getResult();
+}
+
+
+
+
+fault
+rpc::getFault() const {
+
+    switch (this->state) {
+    case STATE_UNFINISHED:
+        throw(error("Attempt to get fault from RPC that is not finished"));
+        break;
+    case STATE_ERROR:
+        throw(*this->errorP);
+        break;
+    case STATE_SUCCEEDED:
+        throw(error("Attempt to get fault from an RPC that succeeded"));
+        break;
+    case STATE_FAILED: {
+        // All normal
+    }
+    }
+
+    return this->outcome.getFault();
+}
+
+
+
+bool
+rpc::isFinished() const {
+    return (this->state != STATE_UNFINISHED);
+}
+
+
+
+bool
+rpc::isSuccessful() const {
+    return (this->state == STATE_SUCCEEDED);
+}
+
+
+
+rpcPtr::rpcPtr() {}
+
+
+
+rpcPtr::rpcPtr(rpc * const rpcP) {
+    this->point(rpcP);
+}
+
+
+
+rpcPtr::rpcPtr(string              const  methodName,
+               xmlrpc_c::paramList const& paramList) {
+
+    this->point(new rpc(methodName, paramList));
+}
+
+
+
+rpc *
+rpcPtr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<rpc *>(p);
+}
+
+
+
+xmlTransaction_client::xmlTransaction_client(
+    clientTransactionPtr const& tranP) :
+    tranP(tranP) {}
+
+
+
+void
+xmlTransaction_client::finish(string const& responseXml) const {
+
+    xml::trace("XML-RPC RESPONSE", responseXml);
+
+    try {
+        rpcOutcome outcome;
+    
+        xml::parseResponse(responseXml, &outcome);
+
+        this->tranP->finish(outcome);
+    } catch (error const& error) {
+        this->tranP->finishErr(error);
+    }
+}
+
+
+
+void
+xmlTransaction_client::finishErr(error const& error) const {
+
+    this->tranP->finishErr(error);
+}
+
+
+
+xmlTransaction_clientPtr::xmlTransaction_clientPtr() {}
+
+
+
+xmlTransaction_clientPtr::xmlTransaction_clientPtr(
+    clientTransactionPtr const& tranP) {
+
+    this->point(new xmlTransaction_client(tranP));
+}
+
+
+
+xmlTransaction_client *
+xmlTransaction_clientPtr::operator->() const {
+    autoObject * const p(this->objectP);
+    return dynamic_cast<xmlTransaction_client *>(p);
+}
+
+
+
+} // namespace
diff --git a/src/cpp/client_simple.cpp b/src/cpp/client_simple.cpp
new file mode 100644 (file)
index 0000000..3387b9e
--- /dev/null
@@ -0,0 +1,169 @@
+#include <string>
+#include <cstring>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "env_wrap.hpp"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/client.hpp"
+#include <xmlrpc-c/client.hpp>
+
+#include "xmlrpc-c/client_simple.hpp"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+namespace xmlrpc_c {
+
+
+namespace {
+
+void
+throwIfError(env_wrap const& env) {
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+}
+
+
+class cValueWrapper {
+/*----------------------------------------------------------------------------
+   Use an object of this class to set up to remove a reference to an
+   xmlrpc_value object (a C object with manual reference management)
+   at then end of a scope -- even if the scope ends with a throw.
+-----------------------------------------------------------------------------*/
+    xmlrpc_value * valueP;
+public:
+    cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {}
+    ~cValueWrapper() { xmlrpc_DECREF(valueP); }
+};
+
+} // namespace
+
+
+
+clientSimple::clientSimple() {
+    
+    clientXmlTransportPtr const transportP(clientXmlTransport_http::create());
+
+    this->clientP = clientPtr(new client_xml(transportP));
+}
+
+
+
+void
+clientSimple::call(string  const serverUrl,
+                   string  const methodName,
+                   value * const resultP) {
+
+    carriageParm_http0 carriageParm(serverUrl);
+
+    rpcPtr rpcPtr(methodName, paramList());
+
+    rpcPtr->call(this->clientP.get(), &carriageParm);
+    
+    *resultP = rpcPtr->getResult();
+}
+
+
+namespace {
+
+void
+makeParamArray(string          const format,
+               xmlrpc_value ** const paramArrayPP,
+               va_list               args) {
+    
+    env_wrap env;
+
+    /* The format is a sequence of parameter specifications, such as
+       "iiii" for 4 integer parameters.  We add parentheses to make it
+       an array of those parameters: "(iiii)".
+    */
+    string const arrayFormat("(" + string(format) + ")");
+    const char * tail;
+
+    xmlrpc_build_value_va(&env.env_c, arrayFormat.c_str(),
+                          args, paramArrayPP, &tail);
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+
+    if (strlen(tail) != 0) {
+        /* xmlrpc_build_value_va() parses off a single value specification
+           from its format string, and 'tail' points to whatever is after
+           it.  Our format string should have been a single array value,
+           meaning tail is end-of-string.  If it's not, that means
+           something closed our array early.
+        */
+        xmlrpc_DECREF(*paramArrayPP);
+        throw(error("format string is invalid.  It apparently has a "
+                    "stray right parenthesis"));
+    }
+}
+
+}  // namespace
+
+
+void
+clientSimple::call(string  const serverUrl,
+                   string  const methodName,
+                   string  const format,
+                   value * const resultP,
+                   ...) {
+
+    carriageParm_http0 carriageParm(serverUrl);
+
+    env_wrap env;
+    xmlrpc_value * paramArrayP;
+
+    va_list args;
+    va_start(args, resultP);
+    makeParamArray(format, &paramArrayP, args);
+    va_end(args);
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+    else {
+        cValueWrapper paramArrayWrapper(paramArrayP); // ensure destruction
+        unsigned int const paramCount(
+            xmlrpc_array_size(&env.env_c, paramArrayP));
+        
+        if (env.env_c.fault_occurred)
+            throw(error(env.env_c.fault_string));
+        
+        paramList paramList;
+        for (unsigned int i = 0; i < paramCount; ++i) {
+            xmlrpc_value * paramP;
+            xmlrpc_array_read_item(&env.env_c, paramArrayP, i, &paramP);
+            if (env.env_c.fault_occurred)
+                throw(error(env.env_c.fault_string));
+            else {
+                cValueWrapper paramWrapper(paramP); // ensure destruction
+                paramList.add(value(paramP));
+            }
+        }
+        rpcPtr rpcPtr(methodName, paramList);
+        rpcPtr->call(this->clientP.get(), &carriageParm);
+        *resultP = rpcPtr->getResult();
+    }
+}
+
+
+
+void
+clientSimple::call(string    const  serverUrl,
+                   string    const  methodName,
+                   paramList const& paramList,
+                   value *   const  resultP) {
+    
+    carriageParm_http0 carriageParm(serverUrl);
+    
+    rpcPtr rpcPtr(methodName, paramList);
+
+    rpcPtr->call(this->clientP.get(), &carriageParm);
+    
+    *resultP = rpcPtr->getResult();
+}
+
+} // namespace
diff --git a/src/cpp/curl.cpp b/src/cpp/curl.cpp
new file mode 100644 (file)
index 0000000..65e8cc3
--- /dev/null
@@ -0,0 +1,285 @@
+/*=============================================================================
+                                curl.cpp
+===============================================================================
+  This is the Curl XML transport of the C++ XML-RPC client library for
+  Xmlrpc-c.
+
+  Note that unlike most of Xmlprc-c's C++ API, this is _not_ based on the
+  C client library.  This code is independent of the C client library, and
+  is based directly on the client XML transport libraries (with a little
+  help from internal C utility libraries).
+=============================================================================*/
+
+#include <stdlib.h>
+#include <cassert>
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/girmem.hpp"
+using girmem::autoObjectPtr;
+using girmem::autoObject;
+#include "env_wrap.hpp"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/transport.h"
+#include "xmlrpc-c/base_int.h"
+
+#include "xmlrpc_curl_transport.h"
+
+/* transport_config.h defines MUST_BUILD_CURL_CLIENT */
+#include "transport_config.h"
+
+#include "xmlrpc-c/client_transport.hpp"
+
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+
+namespace {
+
+class globalConstant {
+public:
+    globalConstant();
+    ~globalConstant();
+};
+
+
+
+globalConstant::globalConstant() {
+
+    // Not thread safe
+
+    xmlrpc_transport_setup setupFn;
+
+#if MUST_BUILD_CURL_CLIENT
+    setupFn = xmlrpc_curl_transport_ops.setup_global_const;
+#else
+    setupFn = NULL;
+#endif
+    if (setupFn) {
+        env_wrap env;
+
+        setupFn(&env.env_c); // Not thread safe
+        
+        if (env.env_c.fault_occurred)
+            throwf("Failed to do global initialization "
+                   "of Curl transport code.  %s", env.env_c.fault_string);
+    }
+}
+
+
+
+globalConstant::~globalConstant() {
+
+    // Not thread safe
+
+    xmlrpc_transport_teardown teardownFn;
+
+#if MUST_BUILD_CURL_CLIENT
+    teardownFn = xmlrpc_curl_transport_ops.teardown_global_const;
+#else
+    teardownFn = NULL;
+#endif
+    if (teardownFn)
+        teardownFn();  // not thread safe
+}
+
+globalConstant globalConst;
+    // This object is never accessed.  Its whole purpose to to be born and
+    // to die, which it does automatically as part of C++ program
+    // program initialization and termination.
+
+} // namespace
+
+
+namespace xmlrpc_c {
+
+carriageParm_curl0::carriageParm_curl0(
+    string const serverUrl
+    ) {
+
+    this->instantiate(serverUrl);
+}
+
+
+
+carriageParm_curl0Ptr::carriageParm_curl0Ptr() {
+    // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParm_curl0Ptr::carriageParm_curl0Ptr(
+    carriageParm_curl0 * const carriageParmP) {
+    this->point(carriageParmP);
+}
+
+
+
+carriageParm_curl0 *
+carriageParm_curl0Ptr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<carriageParm_curl0 *>(p);
+}
+
+
+
+clientXmlTransport_curl::constrOpt::constrOpt() {
+
+    present.network_interface = false;
+    present.no_ssl_verifypeer = false;
+    present.no_ssl_verifyhost = false;
+    present.user_agent = false;
+    present.ssl_cert = false;
+    present.sslcerttype = false;
+    present.sslcertpasswd = false;
+    present.sslkey = false;
+    present.sslkeytype = false;
+    present.sslkeypasswd = false;
+    present.sslengine = false;
+    present.sslengine_default = false;
+    present.sslversion = false;
+    present.cainfo = false;
+    present.capath = false;
+    present.randomfile = false;
+    present.egdsocket = false;
+    present.ssl_cipher_list = false;
+}
+
+
+
+#define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \
+clientXmlTransport_curl::constrOpt & \
+clientXmlTransport_curl::constrOpt::OPTION_NAME(TYPE const& arg) { \
+    this->value.OPTION_NAME = arg; \
+    this->present.OPTION_NAME = true; \
+    return *this; \
+}
+
+DEFINE_OPTION_SETTER(network_interface, string);
+DEFINE_OPTION_SETTER(no_ssl_verifypeer, bool);
+DEFINE_OPTION_SETTER(no_ssl_verifyhost, bool);
+DEFINE_OPTION_SETTER(user_agent, string);
+DEFINE_OPTION_SETTER(ssl_cert, string);
+DEFINE_OPTION_SETTER(sslcerttype, string);
+DEFINE_OPTION_SETTER(sslcertpasswd, string);
+DEFINE_OPTION_SETTER(sslkey, string);
+DEFINE_OPTION_SETTER(sslkeytype, string);
+DEFINE_OPTION_SETTER(sslkeypasswd, string);
+DEFINE_OPTION_SETTER(sslengine, string);
+DEFINE_OPTION_SETTER(sslengine_default, bool);
+DEFINE_OPTION_SETTER(sslversion, xmlrpc_sslversion);
+DEFINE_OPTION_SETTER(cainfo, string);
+DEFINE_OPTION_SETTER(capath, string);
+DEFINE_OPTION_SETTER(randomfile, string);
+DEFINE_OPTION_SETTER(egdsocket, string);
+DEFINE_OPTION_SETTER(ssl_cipher_list, string);
+
+#undef DEFINE_OPTION_SETTER
+
+#if MUST_BUILD_CURL_CLIENT
+
+void
+clientXmlTransport_curl::initialize(constrOpt const& opt) {
+    struct xmlrpc_curl_xportparms transportParms; 
+
+    transportParms.network_interface = opt.present.network_interface ?
+        opt.value.network_interface.c_str() : NULL;
+    transportParms.no_ssl_verifypeer = opt.present.no_ssl_verifypeer ? 
+        opt.value.no_ssl_verifypeer         : false;
+    transportParms.no_ssl_verifyhost = opt.present.no_ssl_verifyhost ? 
+        opt.value.no_ssl_verifyhost         : false;
+    transportParms.user_agent        = opt.present.user_agent ?
+        opt.value.user_agent.c_str()        : NULL;
+    transportParms.ssl_cert          = opt.present.ssl_cert ?
+        opt.value.ssl_cert.c_str()          : NULL;
+    transportParms.sslcerttype       = opt.present.sslcerttype ?
+        opt.value.sslcerttype.c_str()       : NULL;
+    transportParms.sslcertpasswd     = opt.present.sslcertpasswd ?
+        opt.value.sslcertpasswd.c_str()     : NULL;
+    transportParms.sslkey            = opt.present.sslkey ?
+        opt.value.sslkey.c_str()            : NULL;
+    transportParms.sslkeytype        = opt.present.sslkeytype ?
+        opt.value.sslkeytype.c_str()        : NULL;
+    transportParms.sslkeypasswd      = opt.present.sslkeypasswd ?
+        opt.value.sslkeypasswd.c_str()      : NULL;
+    transportParms.sslengine         = opt.present.sslengine ?
+        opt.value.sslengine.c_str()         : NULL;
+    transportParms.sslengine_default = opt.present.sslengine_default ? 
+        opt.value.sslengine_default         : false;
+    transportParms.sslversion        = opt.present.sslversion ? 
+        opt.value.sslversion                : XMLRPC_SSLVERSION_DEFAULT;
+    transportParms.cainfo            = opt.present.cainfo ?
+        opt.value.cainfo.c_str()            : NULL;
+    transportParms.capath            = opt.present.capath ?
+        opt.value.capath.c_str()            : NULL;
+    transportParms.randomfile        = opt.present.randomfile ? 
+        opt.value.randomfile.c_str()        : NULL;
+    transportParms.egdsocket         = opt.present.egdsocket ?
+        opt.value.egdsocket.c_str()         : NULL;
+    transportParms.ssl_cipher_list   = opt.present.ssl_cipher_list ? 
+        opt.value.ssl_cipher_list.c_str()   : NULL;
+
+    this->c_transportOpsP = &xmlrpc_curl_transport_ops;
+
+    env_wrap env;
+
+    xmlrpc_curl_transport_ops.create(
+        &env.env_c, 0, "", "", (xmlrpc_xportparms *)&transportParms,
+        XMLRPC_CXPSIZE(ssl_cipher_list),
+        &this->c_transportP);
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+}
+
+#else  // MUST_BUILD_CURL_CLIENT
+
+void
+clientXmlTransport_curl::initialize(constrOpt const& opt) {
+
+    throw(error("There is no Curl client XML transport in this XML-RPC client "
+                "library"));
+}
+
+#endif
+
+clientXmlTransport_curl::clientXmlTransport_curl(constrOpt const& opt) {
+
+    this->initialize(opt);
+}
+
+
+
+clientXmlTransport_curl::clientXmlTransport_curl(
+    string const networkInterface,
+    bool   const noSslVerifyPeer,
+    bool   const noSslVerifyHost,
+    string const userAgent) {
+
+    clientXmlTransport_curl::constrOpt opt;
+
+    if (networkInterface.size() > 0)
+        opt.network_interface(networkInterface);
+    opt.no_ssl_verifypeer(noSslVerifyPeer);
+    opt.no_ssl_verifyhost(noSslVerifyHost);
+    if (userAgent.size() > 0)
+        opt.user_agent(userAgent);
+
+    this->initialize(opt);
+}
+
+
+
+clientXmlTransport_curl::~clientXmlTransport_curl() {
+
+    this->c_transportOpsP->destroy(this->c_transportP);
+}
+
+
+} // namespace
diff --git a/src/cpp/dll.make b/src/cpp/dll.make
new file mode 100644 (file)
index 0000000..46da433
--- /dev/null
@@ -0,0 +1,13 @@
+# -*-makefile-*-    <-- an Emacs control
+
+# This is stuff for creating Windows DLLs (shared libraries).
+
+# This is to be included by 'Makefile'.  Most of the make variables here
+# come from the main make file.
+
+$(SHLIB_PREFIX)libxmlrpc++$(DLLVER).dll: $(LIBXMLRPCPP_OBJS)
+       $(LD) $(LDSHLIB) -Wl,--export-all-symbols \
+            -Wl,-soname,$@ \
+            -Wl,--out-implib,libxmlrpc++.dll.a -o $@ $(LDFLAGS) \
+            $^ $(LDLIBS) $(LADD) 
diff --git a/src/cpp/dylib.make b/src/cpp/dylib.make
new file mode 100644 (file)
index 0000000..67e6fa8
--- /dev/null
@@ -0,0 +1,21 @@
+# -*-makefile-*-    <-- an Emacs control
+
+# This is stuff for creating Macintosh shared libraries.
+
+# This is to be included by 'Makefile'.  Most of the make variables here
+# come from the main make file.
+
+
+TARGET_LINKNAMES = $(TARGET_LIBRARY_NAMES:%=%.dylib)
+TARGET_SONAMES = $(TARGET_LIBRARY_NAMES:%=%.$(MAJ).dylib
+
+$(TARGET_LINKNAMES): %.dylib : %.$(MAJ).dylib
+       rm -f $@
+       $(SYMLINK) $< $@
+
+$(TARGET_SONAMES): %.dylib : %.$(MIN).dylib
+       rm -f $@
+       $(SYMLINK) $< $@
+
+libxmlrpc++.$(MAJ).$(MIN).dylib: $(LIBXMLRPCPP_OBJS)
+       $(LD) $(LDSHLIB) -o $@ $^ -lc $(LADD)
diff --git a/src/cpp/env_wrap.cpp b/src/cpp/env_wrap.cpp
new file mode 100644 (file)
index 0000000..2ca903f
--- /dev/null
@@ -0,0 +1,18 @@
+#include "xmlrpc-c/util.h"
+
+#include "env_wrap.hpp"
+
+namespace xmlrpc_c {
+
+env_wrap::env_wrap() {
+    xmlrpc_env_init(&this->env_c);
+}
+
+
+
+env_wrap::~env_wrap() {
+    xmlrpc_env_clean(&this->env_c);
+}
+
+
+} // namespace
diff --git a/src/cpp/env_wrap.hpp b/src/cpp/env_wrap.hpp
new file mode 100644 (file)
index 0000000..0172f2b
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef ENV_INT_HPP_INCLUDED
+#define ENV_INT_HPP_INCLUDED
+
+#include "xmlrpc-c/util.h"
+
+namespace xmlrpc_c {
+
+class env_wrap {
+/*----------------------------------------------------------------------------
+   A wrapper to assist in using the Xmlrpc-c C libraries in
+   Xmlrpc-c C++ code.
+
+   To use the C libraries, you have to use type xmlrpc_env, but that type
+   does not have an automatic destructor (because it's C), so it's hard
+   to throw an error from a context in which a variable of that type
+   exists.  This wrapper provides that automatic destructor.
+-----------------------------------------------------------------------------*/
+public:
+    env_wrap();
+    ~env_wrap();
+    xmlrpc_env env_c;
+};
+
+
+} // namespace
+#endif
diff --git a/src/cpp/fault.cpp b/src/cpp/fault.cpp
new file mode 100644 (file)
index 0000000..4db6bc8
--- /dev/null
@@ -0,0 +1,35 @@
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "xmlrpc-c/base.hpp"
+
+using namespace std;
+
+namespace xmlrpc_c {
+
+fault::fault() : valid(false) {};
+    
+fault::fault(string                  const _description,
+             xmlrpc_c::fault::code_t const _code
+             ) :
+    valid(true),
+    code(_code),
+    description(_description)
+    {}
+
+xmlrpc_c::fault::code_t
+fault::getCode() const {
+    if (!valid)
+        throw(error("Attempt to access placeholder xmlrpc_c::fault object"));
+    return this->code;
+}
+
+string
+fault::getDescription() const {
+    if (!valid)
+        throw(error("Attempt to access placeholder xmlrpc_c::fault object"));
+    return this->description;
+}
+
+} // namespace
diff --git a/src/cpp/girerr.cpp b/src/cpp/girerr.cpp
new file mode 100644 (file)
index 0000000..953a2f9
--- /dev/null
@@ -0,0 +1,28 @@
+#include <string>
+
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/girerr.hpp"
+
+using namespace std;
+
+namespace girerr {
+
+void
+throwf(const char * const format, ...) {
+
+    va_list varargs;
+    va_start(varargs, format);
+
+    const char * value;
+    xmlrpc_vasprintf(&value, format, varargs);
+    
+    string const valueString(value);
+
+    xmlrpc_strfree(value);
+
+    throw(girerr::error(valueString));
+
+    va_end(varargs);
+}
+
+} // namespace
diff --git a/src/cpp/girmem.cpp b/src/cpp/girmem.cpp
new file mode 100644 (file)
index 0000000..14b7d00
--- /dev/null
@@ -0,0 +1,156 @@
+#include "pthreadx.h"
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "xmlrpc-c/girmem.hpp"
+
+using namespace std;
+using namespace girmem;
+
+
+namespace girmem {
+
+
+void
+autoObject::incref() {
+    pthread_mutex_lock(&this->refcountLock);
+    ++this->refcount;
+    pthread_mutex_unlock(&this->refcountLock);
+}
+
+
+
+void
+autoObject::decref(bool * const unreferencedP) {
+
+    if (this->refcount == 0)
+        throw(error("Decrementing ref count of unreferenced object"));
+    pthread_mutex_lock(&this->refcountLock);
+    --this->refcount;
+    *unreferencedP = (this->refcount == 0);
+    pthread_mutex_unlock(&this->refcountLock);
+}
+
+
+autoObject::autoObject() {
+    int rc;
+
+    rc = pthread_mutex_init(&this->refcountLock, NULL);
+
+    if (rc != 0)
+        throw(error("Unable to initialize pthread mutex"));
+
+    this->refcount   = 0;
+}
+
+
+
+autoObject::~autoObject() {
+    if (this->refcount > 0)
+        throw(error("Destroying referenced object"));
+
+    int rc;
+
+    rc = pthread_mutex_destroy(&this->refcountLock);
+
+    if (rc != 0)
+        throw(error("Unable to destroy pthread mutex"));
+}
+
+
+
+autoObjectPtr::autoObjectPtr() : objectP(NULL) {}
+
+
+
+autoObjectPtr::autoObjectPtr(autoObject * const objectP) {
+
+    // Note: When someone attempts to use this constructor with a null
+    // argument, it's normally because a 'new' of the autoObject
+    // failed, before calling the autoObject's constructor, thus
+    // generating a null pointer.
+
+    // E.g. the following code, where the system is out of memory:
+    //
+    //    class client    : public autoObject    { ... }
+    //    class clientPtr : public autoObjectPtr { ... }
+    //    clientPtr clientP(new client);
+
+    if (objectP == NULL)
+        throw(error("Object creation failed; trying to create autoObjectPtr "
+                    "ith a null autoObject pointer"));
+        
+    this->objectP = objectP;
+    objectP->incref();
+}
+
+
+
+autoObjectPtr::autoObjectPtr(autoObjectPtr const& autoObjectPtr) {
+    // copy constructor
+
+    this->objectP = autoObjectPtr.objectP;
+    if (this->objectP)
+        this->objectP->incref();
+}
+    
+
+autoObjectPtr::~autoObjectPtr() {
+
+    this->unpoint();
+}
+
+
+void
+autoObjectPtr::point(autoObject * const objectP) {
+
+    if (this->objectP != NULL)
+        throw(error("Already pointing"));
+    this->objectP = objectP;
+    objectP->incref();
+}
+
+
+
+void
+autoObjectPtr::unpoint() {
+
+    if (this->objectP) {
+        bool dead;
+        this->objectP->decref(&dead);
+        if (dead)
+            delete(this->objectP);
+    }
+}
+
+
+
+autoObjectPtr
+autoObjectPtr::operator=(autoObjectPtr const& autoObjectPtr) {
+
+    if (this->objectP != NULL)
+        throw(error("Already pointing"));
+    this->objectP = autoObjectPtr.objectP;
+    this->objectP->incref();
+
+    return *this;
+}
+
+   
+
+autoObject *
+autoObjectPtr::operator->() const {
+    return this->objectP;
+}
+
+
+
+autoObject *
+autoObjectPtr::get() const {
+
+    return this->objectP;
+}
+
+} // namespace
diff --git a/src/cpp/irix.make b/src/cpp/irix.make
new file mode 100644 (file)
index 0000000..22793f7
--- /dev/null
@@ -0,0 +1,22 @@
+# -*-makefile-*-    <-- an Emacs control
+
+# This is stuff for creating Irix shared libraries
+
+# This is to be included by 'Makefile'.  Most of the make variables here
+# come from the main make file.
+
+
+TARGET_LINKNAMES = $(TARGET_LIBRARY_NAMES:%=%.$(SHLIB_SUFFIX)
+
+$(TARGET_LINKNAMES): % : %.$(MAJ).$(MIN)
+       rm -f $@
+       $(SYMLINK) $< $@
+
+LDSHLIB = -lc \
+         -soname $(@:%.$(MAJ)=%) \
+         -set_version `perl -e 'print "sgi$(MAJ).".join(":sgi$(MAJ).",(0..$(MIN)))."\n"'` \
+
+
+libxmlrpc++.$(SHLIB_SUFFIX).$(MAJ): $(LIBXMLRPCPP_OBJS)
+       $(LD) $(LDSHLIB) -o $@ $^ $(LADD)
+
diff --git a/src/cpp/libwww.cpp b/src/cpp/libwww.cpp
new file mode 100644 (file)
index 0000000..3e55539
--- /dev/null
@@ -0,0 +1,160 @@
+/*=============================================================================
+                                libwww.cpp
+===============================================================================
+  This is the Libwww XML transport of the C++ XML-RPC client library for
+  Xmlrpc-c.
+=============================================================================*/
+
+#include <stdlib.h>
+#include <cassert>
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/girmem.hpp"
+using girmem::autoObjectPtr;
+using girmem::autoObject;
+#include "env_wrap.hpp"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/transport.h"
+#include "xmlrpc-c/base_int.h"
+
+#include "xmlrpc_libwww_transport.h"
+
+/* transport_config.h defines MUST_BUILD_LIBWWW_CLIENT */
+#include "transport_config.h"
+
+#include "xmlrpc-c/client_transport.hpp"
+
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+class globalConstant {
+public:
+    globalConstant();
+    ~globalConstant();
+};
+
+
+
+globalConstant::globalConstant() {
+
+    // Not thread safe
+
+    xmlrpc_transport_setup setupFn;
+
+#if MUST_BUILD_LIBWWW_CLIENT
+    setupFn = xmlrpc_libwww_transport_ops.setup_global_const;
+#else
+    setupFn = NULL;
+#endif
+    if (setupFn) {
+        env_wrap env;
+
+        setupFn(&env.env_c); // Not thread safe
+
+        if (env.env_c.fault_occurred)
+            throwf("Failed to do global initialization "
+                   "of Libwww transport code.  %s", env.env_c.fault_string);
+    }
+}
+
+
+
+globalConstant::~globalConstant() {
+
+    // Not thread safe
+
+    xmlrpc_transport_teardown teardownFn;
+
+#if MUST_BUILD_LIBWWW_CLIENT
+    teardownFn = xmlrpc_libwww_transport_ops.teardown_global_const;
+#else
+    teardownFn = NULL;
+#endif
+    if (teardownFn)
+        teardownFn();  // not thread safe
+}
+
+
+globalConstant globalConst;
+    // This object is never accessed.  Its whole purpose to to be born and
+    // to die, which it does automatically as part of C++ program
+    // program initialization and termination.
+
+} // namespace
+
+
+namespace xmlrpc_c {
+
+carriageParm_libwww0::carriageParm_libwww0(
+    string const serverUrl
+    ) {
+
+    this->instantiate(serverUrl);
+}
+
+
+
+carriageParm_libwww0Ptr::carriageParm_libwww0Ptr() {
+    // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParm_libwww0Ptr::carriageParm_libwww0Ptr(
+    carriageParm_libwww0 * const carriageParmP) {
+    this->point(carriageParmP);
+}
+
+
+
+carriageParm_libwww0 *
+carriageParm_libwww0Ptr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<carriageParm_libwww0 *>(p);
+}
+
+
+
+#if MUST_BUILD_LIBWWW_CLIENT
+
+clientXmlTransport_libwww::clientXmlTransport_libwww(
+    string const appname,
+    string const appversion) {
+
+    this->c_transportOpsP = &xmlrpc_libwww_transport_ops;
+
+    env_wrap env;
+
+    xmlrpc_libwww_transport_ops.create(
+        &env.env_c, 0, appname.c_str(), appversion.c_str(), NULL, 0,
+        &this->c_transportP);
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+}
+
+#else  // MUST_BUILD_LIBWWW_CLIENT
+ clientXmlTransport_libwww::clientXmlTransport_libwww(string, string) {
+
+    throw(error("There is no Libwww client XML transport "
+                "in this XML-RPC client library"));
+}
+
+#endif
+
+
+clientXmlTransport_libwww::~clientXmlTransport_libwww() {
+
+    this->c_transportOpsP->destroy(this->c_transportP);
+}
+
+} // namespace
diff --git a/src/cpp/outcome.cpp b/src/cpp/outcome.cpp
new file mode 100644 (file)
index 0000000..e004ef8
--- /dev/null
@@ -0,0 +1,57 @@
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "xmlrpc-c/base.hpp"
+
+using namespace std;
+
+namespace xmlrpc_c {
+
+rpcOutcome::rpcOutcome() : valid(false) {}
+
+rpcOutcome::rpcOutcome(xmlrpc_c::value const result) :
+    valid(true), _succeeded(true), result(result) 
+    {}
+
+
+
+rpcOutcome::rpcOutcome(xmlrpc_c::fault const fault) :
+    valid(true), _succeeded(false), fault(fault)
+    {}
+
+
+
+bool
+rpcOutcome::succeeded() const {
+    if (!valid)
+        throw(error("Attempt to access rpcOutcome object before setting it"));
+    return _succeeded;
+}
+
+
+
+fault
+rpcOutcome::getFault() const {
+    
+    if (!valid)
+        throw(error("Attempt to access rpcOutcome object before setting it"));
+    if (_succeeded)
+        throw(error("Attempt to get fault description from a non-failure "
+                    "RPC outcome"));
+    return fault;
+}
+
+
+
+value
+rpcOutcome::getResult() const {
+    
+    if (!valid)
+        throw(error("Attempt to access rpcOutcome object before setting it"));
+    if (!_succeeded)
+        throw(error("Attempt to get result from an unsuccessful RPC outcome"));
+    return result;
+}
+
+
+} // namespace
+
diff --git a/src/cpp/param_list.cpp b/src/cpp/param_list.cpp
new file mode 100644 (file)
index 0000000..9c69560
--- /dev/null
@@ -0,0 +1,259 @@
+#include <climits>
+#include <cfloat>
+#include <ctime>
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base.hpp"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+namespace xmlrpc_c {
+
+
+paramList::paramList(unsigned int const paramCount) {
+
+    this->paramVector.reserve(paramCount);
+}
+
+
+void
+paramList::add(xmlrpc_c::value const param) {
+
+    this->paramVector.push_back(param);
+}
+
+
+
+unsigned int
+paramList::size() const {
+    return this->paramVector.size();
+}
+
+
+
+xmlrpc_c::value 
+paramList::operator[](unsigned int const subscript) const {
+
+    if (subscript >= this->paramVector.size())
+        throw(girerr::error(
+            "Subscript of xmlrpc_c::paramList out of bounds"));
+
+    return this->paramVector[subscript];
+}
+
+
+
+int
+paramList::getInt(unsigned int const paramNumber,
+                  int          const minimum,
+                  int          const maximum) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    if (this->paramVector[paramNumber].type() != value::TYPE_INT)
+        throw(fault("Parameter that is supposed to be integer is not", 
+                    fault::CODE_TYPE));
+
+    int const intvalue(static_cast<int>(
+        value_int(this->paramVector[paramNumber])));
+
+    if (intvalue < minimum)
+        throw(fault("Integer parameter too low", fault::CODE_TYPE));
+
+    if (intvalue > maximum)
+        throw(fault("Integer parameter too high", fault::CODE_TYPE));
+
+    return intvalue;
+}
+
+
+
+bool
+paramList::getBoolean(unsigned int const paramNumber) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    if (this->paramVector[paramNumber].type() != value::TYPE_BOOLEAN)
+        throw(fault("Parameter that is supposed to be boolean is not", 
+                    fault::CODE_TYPE));
+
+    return static_cast<bool>(value_boolean(this->paramVector[paramNumber]));
+}
+
+
+
+double
+paramList::getDouble(unsigned int const paramNumber,
+                     double       const minimum,
+                     double       const maximum) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    if (this->paramVector[paramNumber].type() != value::TYPE_DOUBLE)
+        throw(fault("Parameter that is supposed to be floating point number "
+                    "is not", 
+                    fault::CODE_TYPE));
+
+    double const doublevalue(static_cast<double>(
+        value_double(this->paramVector[paramNumber])));
+
+    if (doublevalue < minimum)
+        throw(fault("Floating point number parameter too low",
+                    fault::CODE_TYPE));
+
+    if (doublevalue > maximum)
+        throw(fault("Floating point number parameter too high",
+                    fault::CODE_TYPE));
+
+    return doublevalue;
+}
+
+
+
+time_t
+paramList::getDatetime_sec(
+    unsigned int              const paramNumber,
+    paramList::timeConstraint const constraint) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    const xmlrpc_c::value * const paramP(&this->paramVector[paramNumber]);
+
+    if (paramP->type() != value::TYPE_DATETIME)
+        throw(fault("Parameter that is supposed to be a datetime is not", 
+                    fault::CODE_TYPE));
+
+    time_t const timeValue(static_cast<time_t>(value_datetime(*paramP)));
+    time_t const now(time(NULL));
+
+    switch (constraint) {
+    case TC_ANY:
+        /* He'll take anything; no problem */
+        break;
+    case TC_NO_FUTURE:
+        if (timeValue > now)
+            throw(fault("Datetime parameter that is not supposed to be in "
+                        "the future is.", fault::CODE_TYPE));
+        break;
+    case TC_NO_PAST:
+        if (timeValue < now)
+            throw(fault("Datetime parameter that is not supposed to be in "
+                        "the past is.", fault::CODE_TYPE));
+        break;
+    }
+
+    return timeValue;
+}
+
+
+
+string
+paramList::getString(unsigned int const paramNumber) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    if (this->paramVector[paramNumber].type() != value::TYPE_STRING)
+        throw(fault("Parameter that is supposed to be a string is not", 
+                    fault::CODE_TYPE));
+
+    return static_cast<string>(value_string(this->paramVector[paramNumber]));
+}
+
+
+
+std::vector<unsigned char>
+paramList::getBytestring(unsigned int const paramNumber) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    const xmlrpc_c::value * const paramP(&this->paramVector[paramNumber]);
+
+    if (paramP->type() != value::TYPE_BYTESTRING)
+        throw(fault("Parameter that is supposed to be a byte string is not", 
+                    fault::CODE_TYPE));
+
+    return value_bytestring(*paramP).vectorUcharValue();
+}
+
+
+std::vector<xmlrpc_c::value>
+paramList::getArray(unsigned int const paramNumber,
+                     unsigned int const minSize,
+                     unsigned int const maxSize) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    const xmlrpc_c::value * const paramP(&this->paramVector[paramNumber]);
+
+    if (paramP->type() != value::TYPE_ARRAY)
+        throw(fault("Parameter that is supposed to be an array is not", 
+                    fault::CODE_TYPE));
+
+    xmlrpc_c::value_array const arrayValue(*paramP);
+    
+    if (arrayValue.size() < minSize)
+        throw(fault("Array parameter has too few elements",
+                    fault::CODE_TYPE));
+    
+    if (arrayValue.size() > maxSize)
+        throw(fault("Array parameter has too many elements",
+                    fault::CODE_TYPE));
+
+    return value_array(*paramP).vectorValueValue();
+}
+
+
+
+std::map<string, xmlrpc_c::value>
+paramList::getStruct(unsigned int const paramNumber) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    const xmlrpc_c::value * const paramP(&this->paramVector[paramNumber]);
+
+    if (paramP->type() != value::TYPE_STRUCT)
+        throw(fault("Parameter that is supposed to be a structure is not", 
+                    fault::CODE_TYPE));
+
+    return static_cast<std::map<string, xmlrpc_c::value> >(
+        value_struct(*paramP));
+}
+
+
+
+void
+paramList::getNil(unsigned int const paramNumber) const {
+
+    if (paramNumber >= this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+
+    if (this->paramVector[paramNumber].type() != value::TYPE_NIL)
+        throw(fault("Parameter that is supposed to be nil is not", 
+                    fault::CODE_TYPE));
+}
+
+
+
+void
+paramList::verifyEnd(unsigned int const paramNumber) const {
+
+    if (paramNumber < this->paramVector.size())
+        throw(fault("Too many parameters", fault::CODE_TYPE));
+    if (paramNumber > this->paramVector.size())
+        throw(fault("Not enough parameters", fault::CODE_TYPE));
+}
+
+}  // namespace
diff --git a/src/cpp/registry.cpp b/src/cpp/registry.cpp
new file mode 100644 (file)
index 0000000..9a53b92
--- /dev/null
@@ -0,0 +1,365 @@
+#include <cassert>
+#include <string>
+#include <memory>
+#include <algorithm>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "xmlrpc-c/girmem.hpp"
+using girmem::autoObject;
+using girmem::autoObjectPtr;
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base.hpp"
+#include "env_wrap.hpp"
+
+#include "xmlrpc-c/registry.hpp"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+void
+throwIfError(env_wrap const& env) {
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+}
+
+
+} // namespace
+
+namespace xmlrpc_c {
+
+
+method::method() : 
+        _signature("?"),
+        _help("No help is available for this method")
+        {};
+
+
+
+method::~method() {}
+
+
+
+methodPtr::methodPtr(method * const methodP) {
+    this->point(methodP);
+}
+
+
+
+method *
+methodPtr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<method *>(p);
+}
+
+
+
+defaultMethod::~defaultMethod() {}
+
+
+
+defaultMethodPtr::defaultMethodPtr() {}
+
+
+defaultMethodPtr::defaultMethodPtr(defaultMethod * const methodP) {
+    this->point(methodP);
+}
+
+
+
+defaultMethod *
+defaultMethodPtr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<defaultMethod *>(p);
+}
+
+
+
+defaultMethod *
+defaultMethodPtr::get() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<defaultMethod *>(p);
+}
+
+
+
+registry::registry() {
+
+    env_wrap env;
+
+    this->c_registryP = xmlrpc_registry_new(&env.env_c);
+
+    throwIfError(env);
+}
+
+
+
+registry::~registry(void) {
+
+    xmlrpc_registry_free(this->c_registryP);
+}
+
+
+
+registryPtr::registryPtr() {}
+
+
+
+registryPtr::registryPtr(registry * const registryP) {
+    this->point(registryP);
+}
+
+
+
+registry *
+registryPtr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<registry *>(p);
+}
+
+
+
+registry *
+registryPtr::get() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<registry *>(p);
+}
+
+
+
+static xmlrpc_c::paramList
+pListFromXmlrpcArray(xmlrpc_value * const arrayP) {
+/*----------------------------------------------------------------------------
+   Convert an XML-RPC array in C (not C++) form to a parameter list object
+   that can be passed to a method execute method.
+
+   This is glue code to allow us to hook up C++ Xmlrpc-c code to 
+   C Xmlrpc-c code.
+-----------------------------------------------------------------------------*/
+    env_wrap env;
+
+    XMLRPC_ASSERT_ARRAY_OK(arrayP);
+
+    unsigned int const arraySize = xmlrpc_array_size(&env.env_c, arrayP);
+
+    assert(!env.env_c.fault_occurred);
+
+    xmlrpc_c::paramList paramList(arraySize);
+    
+    for (unsigned int i = 0; i < arraySize; ++i) {
+        xmlrpc_value * arrayItemP;
+
+        xmlrpc_array_read_item(&env.env_c, arrayP, i, &arrayItemP);
+        assert(!env.env_c.fault_occurred);
+
+        paramList.add(xmlrpc_c::value(arrayItemP));
+        
+        xmlrpc_DECREF(arrayItemP);
+    }
+    return paramList;
+}
+
+
+
+static xmlrpc_value *
+c_executeMethod(xmlrpc_env *   const envP,
+                xmlrpc_value * const paramArrayP,
+                void *         const methodPtr) {
+/*----------------------------------------------------------------------------
+   This is a function designed to be called via a C registry to
+   execute an XML-RPC method, but use a C++ method object to do the
+   work.  You register this function as the method function and a
+   pointer to the C++ method object as the method data in the C
+   registry.
+
+   If we had a pure C++ registry, this would be unnecessary.
+
+   Since we can't throw an error back to the C code, we catch anything
+   the XML-RPC method's execute() method throws, and any error we
+   encounter in processing the result it returns, and turn it into an
+   XML-RPC method failure.  This will cause a leak if the execute()
+   method actually created a result, since it will not get destroyed.
+-----------------------------------------------------------------------------*/
+    xmlrpc_c::method * const methodP = 
+        static_cast<xmlrpc_c::method *>(methodPtr);
+    xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
+
+    xmlrpc_value * retval;
+
+    try {
+        xmlrpc_c::value result;
+
+        try {
+            methodP->execute(paramList, &result);
+        } catch (xmlrpc_c::fault const& fault) {
+            xmlrpc_env_set_fault(envP, fault.getCode(), 
+                                 fault.getDescription().c_str()); 
+        } catch (girerr::error const& error) {
+            xmlrpc_env_set_fault(envP, 0, error.what());
+        }
+        if (envP->fault_occurred)
+            retval = NULL;
+        else
+            retval = result.cValue();
+    } catch (...) {
+        xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+                             "Unexpected error executing the code for this "
+                             "particular method, detected by the Xmlrpc-c "
+                             "method registry code.  The method did not "
+                             "fail; rather, it did not complete at all.");
+        retval = NULL;
+    }
+    return retval;
+}
+
+
+static xmlrpc_value *
+c_executeDefaultMethod(xmlrpc_env *   const envP,
+                       const char *   const , // host
+                       const char *   const methodName,
+                       xmlrpc_value * const paramArrayP,
+                       void *         const methodPtr) {
+/*----------------------------------------------------------------------------
+   This is a function designed to be called via a C registry to
+   execute an XML-RPC method, but use a C++ method object to do the
+   work.  You register this function as the default method function and a
+   pointer to the C++ default method object as the method data in the C
+   registry.
+
+   If we had a pure C++ registry, this would be unnecessary.
+
+   Since we can't throw an error back to the C code, we catch anything
+   the XML-RPC method's execute() method throws, and any error we
+   encounter in processing the result it returns, and turn it into an
+   XML-RPC method failure.  This will cause a leak if the execute()
+   method actually created a result, since it will not get destroyed.
+-----------------------------------------------------------------------------*/
+    defaultMethod * const methodP = 
+        static_cast<defaultMethod *>(methodPtr);
+    paramList const paramList(pListFromXmlrpcArray(paramArrayP));
+
+    xmlrpc_value * retval;
+
+    try {
+        value result;
+        
+        try {
+            methodP->execute(methodName, paramList, &result);
+        } catch (xmlrpc_c::fault const& fault) {
+            xmlrpc_env_set_fault(envP, fault.getCode(), 
+                                 fault.getDescription().c_str()); 
+        } catch (girerr::error const& error) {
+            xmlrpc_env_set_fault(envP, 0, error.what());
+        }
+        if (envP->fault_occurred)
+            retval = NULL;
+        else
+            retval = result.cValue();
+    } catch (...) {
+        xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+                             "Unexpected error executing the default "
+                             "method code, detected by the Xmlrpc-c "
+                             "method registry code.  The method did not "
+                             "fail; rather, it did not complete at all.");
+        retval = NULL;
+    }
+    return retval;
+}
+
+
+void
+registry::addMethod(string    const name,
+                    methodPtr const methodP) {
+
+    this->methodList.push_back(methodP);
+
+    env_wrap env;
+    
+       xmlrpc_registry_add_method_w_doc(
+        &env.env_c, this->c_registryP, NULL,
+        name.c_str(), &c_executeMethod, 
+        (void*) methodP.get(), 
+        methodP->signature().c_str(), methodP->help().c_str());
+
+    throwIfError(env);
+}
+
+
+
+void
+registry::setDefaultMethod(defaultMethodPtr const methodP) {
+
+    this->defaultMethodP = methodP;
+
+    env_wrap env;
+    
+    xmlrpc_registry_set_default_method(
+        &env.env_c, this->c_registryP,
+        &c_executeDefaultMethod, (void*) methodP.get());
+
+    throwIfError(env);
+}
+
+
+
+void
+registry::disableIntrospection() {
+
+    xmlrpc_registry_disable_introspection(this->c_registryP);
+}
+
+
+
+void
+registry::processCall(string   const& callXml,
+                      string * const  responseXmlP) const {
+/*----------------------------------------------------------------------------
+   Process an XML-RPC call whose XML is 'callXml'.
+
+   Return the response XML as *responseXmlP.
+
+   If we are unable to execute the call, we throw an error.  But if
+   the call executes and the method merely fails in an XML-RPC sense, we
+   don't.  In that case, *responseXmlP indicates the failure.
+-----------------------------------------------------------------------------*/
+    env_wrap env;
+    xmlrpc_mem_block * output;
+
+    // For the pure C++ version, this will have to parse 'callXml'
+    // into a method name and parameters, look up the method name in
+    // the registry, call the method's execute() method, then marshall
+    // the result into XML and return it as *responseXmlP.  It will
+    // also have to execute system methods (e.g. introspection)
+    // itself.  This will be more or less like what
+    // xmlrpc_registry_process_call() does.
+
+    output = xmlrpc_registry_process_call(
+        &env.env_c, this->c_registryP, NULL,
+        callXml.c_str(), callXml.length());
+
+    throwIfError(env);
+
+    *responseXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, output),
+                           XMLRPC_MEMBLOCK_SIZE(char, output));
+    
+    xmlrpc_mem_block_free(output);
+}
+
+xmlrpc_registry *
+registry::c_registry() const {
+
+    return this->c_registryP;
+}
+
+}  // namespace
diff --git a/src/cpp/server_abyss.cpp b/src/cpp/server_abyss.cpp
new file mode 100644 (file)
index 0000000..f4a9090
--- /dev/null
@@ -0,0 +1,372 @@
+#include <cassert>
+#include <cstdlib>
+#include <string>
+#include <memory>
+#include <signal.h>
+#include <errno.h>
+#include <iostream>
+#include <sys/wait.h>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/server_abyss.h"
+#include "xmlrpc-c/registry.hpp"
+#include "xmlrpc-c/server_abyss.hpp"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+namespace xmlrpc_c {
+
+namespace {
+
+
+static void 
+sigterm(int const signalClass) {
+
+    cerr << "Signal of Class " << signalClass << " received.  Exiting" << endl;
+
+    exit(1);
+}
+
+
+
+static void 
+sigchld(int const signalClass) {
+/*----------------------------------------------------------------------------
+   This is a signal handler for a SIGCHLD signal (which informs us that
+   one of our child processes has terminated).
+
+   We respond by reaping the zombie process.
+
+   Implementation note: In some systems, just setting the signal handler
+   to SIG_IGN (ignore signal) does this.  In others, it doesn't.
+-----------------------------------------------------------------------------*/
+#ifndef _WIN32
+    /* Reap zombie children until there aren't any more. */
+
+    bool zombiesExist;
+    bool error;
+
+    assert(signalClass == SIGCHLD);
+    
+    zombiesExist = true;  // initial assumption
+    error = false;  // no error yet
+    while (zombiesExist && !error) {
+        int status;
+        pid_t const pid = waitpid((pid_t) -1, &status, WNOHANG);
+    
+        if (pid == 0)
+            zombiesExist = false;
+        else if (pid < 0) {
+            /* because of ptrace */
+            if (errno == EINTR) {
+                // This is OK - it's a ptrace notification
+            } else
+                error = true;
+        }
+    }
+#endif /* _WIN32 */
+}
+
+
+
+void
+setupSignalHandlers(void) {
+#ifndef _WIN32
+    struct sigaction mysigaction;
+   
+    sigemptyset(&mysigaction.sa_mask);
+    mysigaction.sa_flags = 0;
+
+    /* These signals abort the program, with tracing */
+    mysigaction.sa_handler = sigterm;
+    sigaction(SIGTERM, &mysigaction, NULL);
+    sigaction(SIGINT,  &mysigaction, NULL);
+    sigaction(SIGHUP,  &mysigaction, NULL);
+    sigaction(SIGUSR1, &mysigaction, NULL);
+
+    /* This signal indicates connection closed in the middle */
+    mysigaction.sa_handler = SIG_IGN;
+    sigaction(SIGPIPE, &mysigaction, NULL);
+   
+    /* This signal indicates a child process (request handler) has died */
+    mysigaction.sa_handler = sigchld;
+    sigaction(SIGCHLD, &mysigaction, NULL);
+#endif
+}    
+
+
+} // namespace
+
+
+
+serverAbyss::constrOpt::constrOpt() {
+    present.registryPtr      = false;
+    present.registryP        = false;
+    present.socketFd         = false;
+    present.portNumber       = false;
+    present.logFileName      = false;
+    present.keepaliveTimeout = false;
+    present.keepaliveMaxConn = false;
+    present.timeout          = false;
+    present.dontAdvertise    = false;
+    present.uriPath          = false;
+    present.chunkResponse    = false;
+    
+    // Set default values
+    value.dontAdvertise = false;
+    value.uriPath       = string("/RPC2");
+    value.chunkResponse = false;
+}
+
+
+
+#define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \
+serverAbyss::constrOpt & \
+serverAbyss::constrOpt::OPTION_NAME(TYPE const& arg) { \
+    this->value.OPTION_NAME = arg; \
+    this->present.OPTION_NAME = true; \
+    return *this; \
+}
+
+DEFINE_OPTION_SETTER(registryPtr,      xmlrpc_c::registryPtr);
+DEFINE_OPTION_SETTER(registryP,        const registry *);
+DEFINE_OPTION_SETTER(socketFd,         xmlrpc_socket);
+DEFINE_OPTION_SETTER(portNumber,       uint);
+DEFINE_OPTION_SETTER(logFileName,      string);
+DEFINE_OPTION_SETTER(keepaliveTimeout, uint);
+DEFINE_OPTION_SETTER(keepaliveMaxConn, uint);
+DEFINE_OPTION_SETTER(timeout,          uint);
+DEFINE_OPTION_SETTER(dontAdvertise,    bool);
+DEFINE_OPTION_SETTER(uriPath,          string);
+DEFINE_OPTION_SETTER(chunkResponse,    bool);
+
+
+
+void
+serverAbyss::setAdditionalServerParms(constrOpt const& opt) {
+
+    /* The following ought to be parameters on ServerCreate(), but it
+       looks like plugging them straight into the TServer structure is
+       the only way to set them.  
+    */
+
+    if (opt.present.keepaliveTimeout)
+        ServerSetKeepaliveTimeout(&this->cServer, opt.value.keepaliveTimeout);
+    if (opt.present.keepaliveMaxConn)
+        ServerSetKeepaliveMaxConn(&this->cServer, opt.value.keepaliveMaxConn);
+    if (opt.present.timeout)
+        ServerSetTimeout(&this->cServer, opt.value.timeout);
+    ServerSetAdvertise(&this->cServer, !opt.value.dontAdvertise);
+}
+
+
+
+static void
+createServer(bool         const  logFileNameGiven,
+             string       const& logFileName,
+             bool         const  socketFdGiven,
+             int          const  socketFd,
+             bool         const  portNumberGiven,
+             unsigned int const  portNumber,
+             TServer *    const  srvPP) {
+             
+    const char * const logfileArg(logFileNameGiven ? 
+                                  logFileName.c_str() : NULL);
+
+    const char * const serverName("XmlRpcServer");
+
+    bool created;
+        
+    if (socketFdGiven)
+        created =
+            ServerCreateSocket(srvPP, serverName, socketFd,
+                               DEFAULT_DOCS, logfileArg);
+    else if (portNumberGiven) {
+        if (portNumber > 0xffff)
+            throwf("Port number %u exceeds the maximum possible port number "
+                   "(65535)", portNumber);
+
+        created =
+            ServerCreate(srvPP, serverName, portNumber,
+                         DEFAULT_DOCS, logfileArg);
+    } else
+        created = 
+            ServerCreateNoAccept(srvPP, serverName,
+                                 DEFAULT_DOCS, logfileArg);
+
+    if (!created)
+        throw(error("Failed to create Abyss server.  See Abyss error log for "
+                    "reason."));
+}
+
+
+
+void
+serverAbyss::initialize(constrOpt const& opt) {
+
+    const registry * registryP;
+
+    if (!opt.present.registryP && !opt.present.registryPtr)
+        throwf("You must specify the 'registryP' or 'registryPtr' option");
+    else if (opt.present.registryP && opt.present.registryPtr)
+        throwf("You may not specify both the 'registryP' and "
+               "the 'registryPtr' options");
+    else {
+        if (opt.present.registryP)
+            registryP = opt.value.registryP;
+        else {
+            this->registryPtr = opt.value.registryPtr;
+            registryP = this->registryPtr.get();
+        }
+    }
+    if (opt.present.portNumber && opt.present.socketFd)
+        throwf("You can't specify both portNumber and socketFd options");
+
+    DateInit();
+    
+    createServer(opt.present.logFileName, opt.value.logFileName,
+                 opt.present.socketFd,    opt.value.socketFd,
+                 opt.present.portNumber,  opt.value.portNumber,
+                 &this->cServer);
+
+    try {
+        setAdditionalServerParms(opt);
+        
+        // chunked response implementation is incomplete.  We must
+        // eventually get away from libxmlrpc_server_abyss and
+        // register our own handler with the Abyss server.  At that
+        // time, we'll have some place to pass
+        // opt.value.chunkResponse.
+        
+        xmlrpc_c::server_abyss_set_handlers(&this->cServer,
+                                            registryP,
+                                            opt.value.uriPath);
+        
+        if (opt.present.portNumber || opt.present.socketFd)
+            ServerInit(&this->cServer);
+        
+        setupSignalHandlers();
+    } catch (...) {
+        ServerFree(&this->cServer);
+        throw;
+    }
+}
+
+
+
+serverAbyss::serverAbyss(constrOpt const& opt) {
+
+    initialize(opt);
+}
+
+
+
+serverAbyss::serverAbyss(
+    xmlrpc_c::registry const& registry,
+    unsigned int       const  portNumber,
+    string             const& logFileName,
+    unsigned int       const  keepaliveTimeout,
+    unsigned int       const  keepaliveMaxConn,
+    unsigned int       const  timeout,
+    bool               const  dontAdvertise,
+    bool               const  socketBound,
+    xmlrpc_socket      const  socketFd) {
+/*----------------------------------------------------------------------------
+  This is a backward compatibility interface.  This used to be the only
+  constructor.
+-----------------------------------------------------------------------------*/
+    serverAbyss::constrOpt opt;
+
+    opt.registryP(&registry);
+    if (logFileName.length() > 0)
+        opt.logFileName(logFileName);
+    if (keepaliveTimeout > 0)
+        opt.keepaliveTimeout(keepaliveTimeout);
+    if (keepaliveMaxConn > 0)
+        opt.keepaliveMaxConn(keepaliveMaxConn);
+    if (timeout > 0)
+        opt.timeout(timeout);
+    opt.dontAdvertise(dontAdvertise);
+    if (socketBound)
+        opt.socketFd(socketFd);
+    else
+        opt.portNumber(portNumber);
+
+    initialize(opt);
+}
+
+
+
+serverAbyss::~serverAbyss() {
+
+    ServerFree(&this->cServer);
+}
+
+
+
+void
+serverAbyss::run() {
+
+    ServerRun(&this->cServer);
+}
+
+
+void
+serverAbyss::runOnce() {
+
+    ServerRunOnce(&this->cServer);
+}
+
+
+
+void
+serverAbyss::runConn(int const socketFd) {
+
+    ServerRunConn(&this->cServer, socketFd);
+}
+
+
+
+void
+server_abyss_set_handlers(TServer * const  srvP,
+                          registry  const& registry,
+                          string    const& uriPath) {
+
+    xmlrpc_server_abyss_set_handlers2(srvP,
+                                      uriPath.c_str(),
+                                      registry.c_registry());
+}
+
+
+
+void
+server_abyss_set_handlers(TServer *        const  srvP,
+                          const registry * const  registryP,
+                          string           const& uriPath) {
+
+    xmlrpc_server_abyss_set_handlers2(srvP,
+                                      uriPath.c_str(),
+                                      registryP->c_registry());
+}
+
+
+
+void
+server_abyss_set_handlers(TServer *   const  srvP,
+                          registryPtr const  registryPtr,
+                          string      const& uriPath) {
+
+    xmlrpc_server_abyss_set_handlers2(srvP,
+                                      uriPath.c_str(),
+                                      registryPtr->c_registry());
+}
+
+
+
+} // namespace
diff --git a/src/cpp/test/.cvsignore b/src/cpp/test/.cvsignore
new file mode 100644 (file)
index 0000000..9daeafb
--- /dev/null
@@ -0,0 +1 @@
+test
diff --git a/src/cpp/test/Makefile b/src/cpp/test/Makefile
new file mode 100644 (file)
index 0000000..eab1e8f
--- /dev/null
@@ -0,0 +1,91 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../../..
+endif
+SUBDIR = src/test/cpp
+# BLDDIR is for use in places where a symbolic link won't work.
+# BUILDDIR is for places in Makefile.common that can use the 'blddir'
+# symbolic link (but in other directories, doesn't).
+BLDDIR = ../../..
+BUILDDIR = blddir
+VPATH = .:$(SRCDIR)
+
+include $(BLDDIR)/Makefile.config
+
+PROGS = test
+
+default: all
+
+all: $(PROGS)
+
+XMLRPC_C_CONFIG = $(BUILDDIR)/xmlrpc-c-config.test
+
+CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+LDFLAGS += $(shell $(XMLRPC_C_CONFIG) client --ldadd)
+
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+  LDFLAGS += $(shell curl-config --libs)
+endif
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+  LDFLAGS += $(shell libwww-config --libs)
+endif
+
+LDFLAGS += "-lpthread"
+
+LDFLAGS += $(LADD)
+
+INCLUDES = -Isrcdir/include -Iblddir -Isrcdir -Isrcdir/lib/util/include
+
+# This 'Makefile' dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+Makefile: blddir srcdir
+
+include $(SRCDIR)/Makefile.common
+
+
+TEST_OBJS = test.o server_abyss.o tools.o
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  TEST_OBJS += testclient.o
+  CLIENT_LIBS = $(LIBXMLRPC_CLIENT++) $(LIBXMLRPC_CLIENT_A)
+else
+  TEST_OBJS += testclient_dummy.o
+  CLIENT_LIBS =
+endif
+
+
+test:$(TEST_OBJS) $(LIBXMLRPC_SERVER_ABYSS++) $(LIBXMLRPC_SERVER++) \
+  $(CLIENT_LIBS) $(LIBXMLRPC++) $(LIBXMLRPC_CPP) \
+  $(LIBXMLRPC_SERVER_ABYSS_A) $(LIBXMLRPC_SERVER_A) \
+  $(LIBXMLRPC_A) $(LIBXMLRPC_ABYSS_A) $(LIBXMLRPC_XML) $(LIBXMLRPC_UTIL_A) 
+       $(LIBTOOL) --mode=link $(CXXLD) -o $@ $(LDFLAGS) $^
+
+%.o:%.cpp
+       $(CXX) -c $(INCLUDES) $(CXXFLAGS) $<
+
+# Note the difference between 'check' and 'runtests'.  'check' means to check
+# our own correctness.  'runtests' means to run the tests that check our
+# parent's correctness
+
+.PHONY: check
+check:
+
+.PHONY: runtests
+runtests: test
+       ./test
+
+.PHONY: install
+install:
+
+.PHONY: clean clean-local distclean
+clean: clean-common clean-local
+clean-local:
+       rm -f $(PROGS)
+
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
+
+include Makefile.depend
diff --git a/src/cpp/test/Makefile.depend b/src/cpp/test/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/cpp/test/server_abyss.cpp b/src/cpp/test/server_abyss.cpp
new file mode 100644 (file)
index 0000000..b1a6bda
--- /dev/null
@@ -0,0 +1,215 @@
+/*=============================================================================
+                                  server_abyss
+===============================================================================
+  Test the Abyss server C++ facilities of XML-RPC for C/C++.
+  
+=============================================================================*/
+#include <sys/unistd.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <string>
+#include <iostream>
+#include <vector>
+#include <sstream>
+#include <memory>
+#include <time.h>
+#include <cstring>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/registry.hpp"
+#include "xmlrpc-c/server_abyss.hpp"
+
+#include "tools.hpp"
+#include "server_abyss.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+
+
+class boundSocket {
+
+public:
+    boundSocket(short const portNumber) {
+        this->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+        if (this->fd < 0)
+            throwf("socket() failed.  errno=%d (%s)",
+                   errno, strerror(errno));
+        
+        struct sockaddr_in sockAddr;
+        int rc;
+
+        sockAddr.sin_family = AF_INET;
+        sockAddr.sin_port   = htons(portNumber);
+        sockAddr.sin_addr.s_addr = 0;
+
+        rc = bind(this->fd, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
+        
+        if (rc != 0) {
+            close(this->fd);
+            throwf("Couldn't bind.  bind() failed with errno=%d (%s)",
+                   errno, strerror(errno));
+        }
+    }
+
+    ~boundSocket() {
+        close(this->fd);
+    }
+
+    int fd;
+};
+
+
+
+class sampleAddMethod : public method {
+public:
+    sampleAddMethod() {
+        this->_signature = "i:ii";
+        this->_help = "This method adds two integers together";
+    }
+    void
+    execute(xmlrpc_c::paramList const& paramList,
+            value *             const  retvalP) {
+        
+        int const addend(paramList.getInt(0));
+        int const adder(paramList.getInt(1));
+        
+        paramList.verifyEnd(2);
+        
+        *retvalP = value_int(addend + adder);
+    }
+};
+
+
+
+class addHandlerTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "addHandlerTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+        TServer abyssServer;
+
+        ServerCreate(&abyssServer, "testserver", 8080, NULL, NULL);
+
+        registry myRegistry;
+        
+        myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+        
+        registryPtr myRegistryP(new registry);
+        
+        myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+        server_abyss_set_handlers(&abyssServer, myRegistry);
+
+        server_abyss_set_handlers(&abyssServer, &myRegistry);
+        
+        server_abyss_set_handlers(&abyssServer, myRegistryP);
+
+        server_abyss_set_handlers(&abyssServer, myRegistry, "/RPC3");
+
+        server_abyss_set_handlers(&abyssServer, &myRegistry, "/RPC3");
+        
+        server_abyss_set_handlers(&abyssServer, myRegistryP, "/RPC3");
+
+        ServerFree(&abyssServer);
+    }
+};
+
+
+
+string
+serverAbyssTestSuite::suiteName() {
+    return "serverAbyssTestSuite";
+}
+
+
+void
+serverAbyssTestSuite::runtests(unsigned int const indentation) {
+
+    addHandlerTestSuite().run(indentation+1);
+
+    registry myRegistry;
+        
+    myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+    registryPtr myRegistryP(new registry);
+
+    myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+    EXPECT_ERROR(  // No registry
+        serverAbyss::constrOpt opt;
+        serverAbyss abyssServer(opt);
+        );
+    EXPECT_ERROR(  // Both portNumber and socketFd
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .portNumber(8080)
+                                .socketFd(3));
+        );
+
+    // Due to the vagaries of Abyss, construction of the following
+    // objects may exit the program if it detects an error, such as
+    // port number already in use.  We need to fix Abyss some day.
+
+    {
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryP(&myRegistry)
+                                .portNumber(12345)
+            );
+    }
+    {
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryPtr(myRegistryP)
+                                .portNumber(12345)
+            );
+
+        EXPECT_ERROR(  // Both registryP and registryPtr
+            serverAbyss abyssServer(serverAbyss::constrOpt()
+                                    .registryPtr(myRegistryP)
+                                    .registryP(&myRegistry)
+                                    .portNumber(12345)
+                );
+            );
+    }
+    {
+        boundSocket socket(12345);
+        
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryP(&myRegistry)
+                                .socketFd(socket.fd)
+            );
+    }
+    {
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryP(&myRegistry)
+            );
+    }
+
+    {
+        // Test all the options
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryPtr(myRegistryP)
+                                .portNumber(12345)
+                                .logFileName("/tmp/logfile")
+                                .keepaliveTimeout(5)
+                                .keepaliveMaxConn(4)
+                                .timeout(20)
+                                .dontAdvertise(true)
+                                .uriPath("/xmlrpc")
+            );
+
+    }
+    {
+        serverAbyss abyssServer(
+            myRegistry,
+            12345,              // TCP port on which to listen
+            "/tmp/xmlrpc_log"  // Log file
+            );
+    }
+}
diff --git a/src/cpp/test/server_abyss.hpp b/src/cpp/test/server_abyss.hpp
new file mode 100644 (file)
index 0000000..afd801d
--- /dev/null
@@ -0,0 +1,8 @@
+#include "tools.hpp"
+
+class serverAbyssTestSuite : public testSuite {
+
+public:
+    virtual std::string suiteName();
+    virtual void runtests(unsigned int);
+};
diff --git a/src/cpp/test/test.cpp b/src/cpp/test/test.cpp
new file mode 100644 (file)
index 0000000..e026535
--- /dev/null
@@ -0,0 +1,820 @@
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <sstream>
+#include <memory>
+#include <time.h>
+#include <cstring>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "transport_config.h"
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/oldcppwrapper.hpp"
+#include "xmlrpc-c/registry.hpp"
+
+#include "testclient.hpp"
+#include "server_abyss.hpp"
+#include "tools.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+//=========================================================================
+//  Test Harness
+//=========================================================================
+// 
+//  There are two styles of test in here.  The older ones are vaguely
+//  inspired by Kent Beck's book on eXtreme Programming (XP) and use
+//  the TEST...() macros.
+//
+//  But this style is not really appropriate for C++.  It's based on
+//  code that explicitly tests for errors, as one would do in C.  In C++,
+//  it is cumbersome to catch exceptions on every call, so we don't in
+//  the new style.
+
+//  And there's not much point in trying to count test successes and
+//  failures.  Any failure is a problem, so in the new style, we just
+//  quit after we recognize one (again, more in line with regular exception
+//  throwing).  With exception throwing, you can't count what _didn't_
+//  cause an exception, so there's no meaningful count of test successes.
+//
+//  To run the tests, type './cpptest'.
+//  To check for memory leaks, install RedHat's 'memprof' utility, and
+//  type 'memprof cpptest'.
+//
+//  If you add new tests to this file, please deallocate any data
+//  structures you use in the appropriate fashion. This allows us to test
+//  various destructor code for memory leaks.
+
+
+class sampleAddMethod : public method {
+public:
+    sampleAddMethod() {
+        this->_signature = "i:ii";
+        this->_help = "This method adds two integers together";
+    }
+    void
+    execute(xmlrpc_c::paramList const& paramList,
+            value *             const  retvalP) {
+        
+        int const addend(paramList.getInt(0));
+        int const adder(paramList.getInt(1));
+        
+        paramList.verifyEnd(2);
+        
+        *retvalP = value_int(addend + adder);
+    }
+};
+
+
+
+class nameMethod : public defaultMethod {
+
+    void
+    execute(string              const& methodName,
+            xmlrpc_c::paramList const& ,  // paramList
+            value *             const  retvalP) {
+        
+        *retvalP = value_string(string("no such method: ") + methodName);
+    }
+};
+
+
+//=========================================================================
+//  Test Suites
+//=========================================================================
+
+void 
+test_fault (void) {
+
+    // Create a new fault and perform basic operations.
+    XmlRpcFault fault1 = XmlRpcFault(6, "Sample fault");
+    TEST(fault1.getFaultCode() == 6);
+    TEST(fault1.getFaultString() == "Sample fault");
+
+    // Extract and examine the underlying xmlrpc_env struct.
+    xmlrpc_env *env1 = fault1.getFaultEnv();
+    TEST(env1 != NULL);
+    TEST(env1->fault_occurred);
+    TEST(env1->fault_code == 6);
+    TEST(strcmp(env1->fault_string, "Sample fault") == 0);
+
+    // Test our copy constructor.
+    XmlRpcFault fault2 = fault1;
+    TEST(fault2.getFaultCode() == 6);
+    TEST(fault2.getFaultString() == "Sample fault");
+    
+    // Construct a fault from a pre-existing xmlrpc_env structure.
+    xmlrpc_env env3;
+    xmlrpc_env_init(&env3);
+    xmlrpc_env_set_fault(&env3, 7, "Another fault");
+    XmlRpcFault fault3 = XmlRpcFault(&env3);
+    xmlrpc_env_clean(&env3);
+    TEST(fault3.getFaultCode() == 7);
+    TEST(fault3.getFaultString() == "Another fault");
+    
+    // Attempt to construct a fault from a fault-free xmlrpc_env.
+    xmlrpc_env env4;
+    xmlrpc_env_init(&env4);
+    try {
+        XmlRpcFault fault4 = XmlRpcFault(&env4);
+        TEST_FAILED("Constructed invalid XmlRpcFault");
+    } catch (XmlRpcFault const& fault) {
+        TEST_PASSED();
+        TEST(fault.getFaultCode() == XMLRPC_INTERNAL_ERROR);
+    }
+    xmlrpc_env_clean(&env4);
+}
+
+
+
+void test_env (void) {
+
+    // Declare these here to prevent silly compiler warnings about
+    // potentially uninitialized variables.
+    XmlRpcEnv env1;
+    XmlRpcEnv env2;
+
+    // Perform simple environment tests.
+    TEST(!env1.hasFaultOccurred());
+    xmlrpc_env_set_fault(env1, 8, "Fault 8");
+    TEST(env1.hasFaultOccurred());
+    XmlRpcFault fault1 = env1.getFault();
+    TEST(fault1.getFaultCode() == 8);
+    TEST(fault1.getFaultString() == "Fault 8");
+
+    // Test throwIfFaultOccurred.
+    try {
+        env2.throwIfFaultOccurred();
+        TEST_PASSED();
+    } catch (XmlRpcFault const& fault) {
+        TEST_FAILED("We threw a fault when one hadn't occurred");
+    } 
+    xmlrpc_env_set_fault(env2, 9, "Fault 9");
+    try {
+        env2.throwIfFaultOccurred();
+        TEST_FAILED("A fault occurred, and we didn't throw it");
+    } catch (XmlRpcFault const& fault) {
+        TEST_PASSED();
+        TEST(fault.getFaultCode() == 9);
+        TEST(fault.getFaultString() == "Fault 9");
+    } 
+    
+    // Make sure we can't get a fault if one hasn't occurred.
+    XmlRpcEnv env3;
+    try {
+        XmlRpcFault fault3 = env3.getFault();
+        TEST_FAILED("We retrieved a non-existant fault");
+    } catch (XmlRpcFault const& fault) {
+        TEST_PASSED();
+        TEST(fault.getFaultCode() == XMLRPC_INTERNAL_ERROR);
+    }
+}
+
+void test_value (void) {
+    XmlRpcEnv env;
+
+    // Test basic reference counting behavior.
+    xmlrpc_value *v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 1);
+    env.throwIfFaultOccurred();
+    XmlRpcValue val1 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+    v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 2);
+    env.throwIfFaultOccurred();
+    XmlRpcValue val2 = v;
+    xmlrpc_DECREF(v);
+
+    // Borrow a reference.
+    v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 3);
+    env.throwIfFaultOccurred();
+    XmlRpcValue val3 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+    xmlrpc_value *borrowed = val3.borrowReference();
+    TEST(borrowed == v);
+
+    // Make a reference.
+    v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 4);
+    env.throwIfFaultOccurred();
+    XmlRpcValue val4 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+    xmlrpc_value *made = val4.makeReference();
+    TEST(made == v);
+    xmlrpc_DECREF(made);
+
+    // Test our default constructor.
+    XmlRpcValue val5;
+    TEST(val5.getBool() == false);
+
+    // Test our type introspection.
+    TEST(XmlRpcValue::makeInt(0).getType() == XMLRPC_TYPE_INT);
+    
+    // Test our basic data types.
+    TEST(XmlRpcValue::makeInt(30).getInt() == 30);
+    TEST(XmlRpcValue::makeInt(-30).getInt() == -30);
+    TEST(XmlRpcValue::makeBool(true).getBool() == true);
+    TEST(XmlRpcValue::makeBool(false).getBool() == false);
+    TEST(XmlRpcValue::makeDateTime("19980717T14:08:55").getRawDateTime() ==
+         "19980717T14:08:55");
+    TEST(XmlRpcValue::makeString("foo").getString() == "foo");
+    TEST(XmlRpcValue::makeString("bar", 3).getString() == "bar");
+    TEST(XmlRpcValue::makeString("bar", 3).getString() == "bar");
+    TEST(XmlRpcValue::makeString("a\0b").getString() == string("a\0b"));
+    XmlRpcValue::makeArray().getArray();
+    XmlRpcValue::makeStruct().getStruct();
+
+    // Test Base64 values.
+    const unsigned char *b64_data;
+    size_t b64_len;
+    XmlRpcValue val6 = XmlRpcValue::makeBase64((unsigned char*) "a\0\0b", 4);
+    val6.getBase64(b64_data, b64_len);
+    TEST(b64_len == 4);
+    TEST(memcmp(b64_data, "a\0\0b", 4) == 0);
+
+    // Test arrays.
+    XmlRpcValue array = XmlRpcValue::makeArray();
+    TEST(array.arraySize() == 0);
+    array.arrayAppendItem(XmlRpcValue::makeString("foo"));
+    TEST(array.arraySize() == 1);
+    array.arrayAppendItem(XmlRpcValue::makeString("bar"));
+    TEST(array.arraySize() == 2);
+    TEST(array.arrayGetItem(0).getString() == "foo");
+    TEST(array.arrayGetItem(1).getString() == "bar");
+
+    // Test structs.
+    XmlRpcValue strct = XmlRpcValue::makeStruct();
+    TEST(strct.structSize() == 0);
+    strct.structSetValue("foo", XmlRpcValue::makeString("fooval"));
+    TEST(strct.structSize() == 1);
+    strct.structSetValue("bar", XmlRpcValue::makeString("barval"));
+    TEST(strct.structSize() == 2);
+    TEST(strct.structHasKey("bar"));
+    TEST(!strct.structHasKey("nosuch"));
+    for (size_t i = 0; i < strct.structSize(); i++) {
+        string key;
+        XmlRpcValue value;
+        strct.structGetKeyAndValue(i, key, value);
+        TEST(key + "val" == value.getString());
+    }
+}
+
+
+
+static void
+testXmlRpcCpp() {
+/*----------------------------------------------------------------------------
+   Test the legacy XmlRpcCpp.cpp library
+-----------------------------------------------------------------------------*/
+    cout << "Testing XmlRpcCpp library..." << endl;
+
+    test_fault();
+    test_env();
+    test_value();
+}
+
+
+
+class intTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "intTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        value_int int1(7);
+        TEST(static_cast<int>(int1) == 7);
+        value_int int2(-7);
+        TEST(static_cast<int>(int2) == -7);
+        value val1(int1);
+        TEST(val1.type() == value::TYPE_INT);
+        value_int int3(val1);
+        TEST(static_cast<int>(int3) == 7);
+        try {
+            value_int int4(value_double(3.7));
+            TEST_FAILED("invalid cast double-int suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class doubleTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "doubleTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        value_double double1(3.14);
+        TEST(static_cast<double>(double1) == 3.14);
+        value val1(double1);
+        TEST(val1.type() == value::TYPE_DOUBLE);
+        value_double double2(val1);
+        TEST(static_cast<double>(double2) == 3.14);
+        try {
+            value_double double4(value_int(4));
+            TEST_FAILED("invalid cast int-double suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class booleanTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "booleanTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        value_boolean boolean1(true); 
+        TEST(static_cast<bool>(boolean1) == true);
+        value_boolean boolean2(false);
+        TEST(static_cast<bool>(boolean2) == false);
+        value val1(boolean1);
+        TEST(val1.type() == value::TYPE_BOOLEAN);
+        value_boolean boolean3(val1);
+        TEST(static_cast<bool>(boolean3) == true);
+        try {
+            value_boolean boolean4(value_int(4));
+            TEST_FAILED("invalid cast int-boolean suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class datetimeTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "datetimeTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        time_t const testTime(900684535);
+        value_datetime datetime1("19980717T14:08:55");
+        TEST(static_cast<time_t>(datetime1) == testTime);
+        value_datetime datetime2(testTime);
+        TEST(static_cast<time_t>(datetime2) == testTime);
+        value val1(datetime1);
+        TEST(val1.type() == value::TYPE_DATETIME);
+        value_datetime datetime3(val1);
+        TEST(static_cast<time_t>(datetime3) == testTime);
+        try {
+            value_datetime datetime4(value_int(4));
+            TEST_FAILED("invalid cast int-datetime suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class stringTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "stringTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        value_string string1("hello world");
+        TEST(static_cast<string>(string1) == "hello world");
+        value_string string2("embedded\0null");
+        TEST(static_cast<string>(string2) == "embedded\0null");
+        value val1(string1);
+        TEST(val1.type() == value::TYPE_STRING);
+        value_string string3(val1);
+        TEST(static_cast<string>(string3) == "hello world");
+        try {
+            value_string string4(value_int(4));
+            TEST_FAILED("invalid cast int-string suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class bytestringTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "bytestringTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        unsigned char bytestringArray[] = {0x10, 0x11, 0x12, 0x13, 0x14};
+        vector<unsigned char> 
+            bytestringData(&bytestringArray[0], &bytestringArray[4]);
+        value_bytestring bytestring1(bytestringData);
+
+        vector<unsigned char> const dataReadBack1(
+            bytestring1.vectorUcharValue());
+        TEST(dataReadBack1 == bytestringData);
+        value val1(bytestring1);
+        TEST(val1.type() == value::TYPE_BYTESTRING);
+        value_bytestring bytestring2(val1);
+        vector<unsigned char> const dataReadBack2(
+            bytestring2.vectorUcharValue());
+        TEST(dataReadBack2 == bytestringData);
+        try {
+            value_bytestring bytestring4(value_int(4));
+            TEST_FAILED("invalid cast int-bytestring suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class nilTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "nilTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        value_nil nil1;
+        value val1(nil1);
+        TEST(val1.type() == value::TYPE_NIL);
+        value_nil nil2(val1);
+        try {
+            value_nil nil4(value_int(4));
+            TEST_FAILED("invalid cast int-nil suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class structTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "structTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        map<string, value> structData;
+        pair<string, value> member("the_integer", value_int(9));
+        structData.insert(member);
+        
+        value_struct struct1(structData);
+
+        map<string, value> dataReadBack(struct1);
+
+        TEST(static_cast<int>(value_int(dataReadBack["the_integer"])) == 9);
+
+        value val1(struct1);
+        TEST(val1.type() == value::TYPE_STRUCT);
+        value_struct struct2(val1);
+        try {
+            value_struct struct4(value_int(4));
+            TEST_FAILED("invalid cast int-struct suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class arrayTestSuite : public testSuite {
+public:
+    virtual string suiteName() {
+        return "arrayTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        vector<value> arrayData;
+        arrayData.push_back(value_int(7));
+        arrayData.push_back(value_double(2.78));
+        arrayData.push_back(value_string("hello world"));
+        value_array array1(arrayData);
+
+        TEST(array1.size() == 3);
+        vector<value> dataReadBack1(array1.vectorValueValue());
+        TEST(dataReadBack1[0].type() ==  value::TYPE_INT);
+        TEST(static_cast<int>(value_int(dataReadBack1[0])) == 7);
+        TEST(dataReadBack1[1].type() ==  value::TYPE_DOUBLE);
+        TEST(static_cast<double>(value_double(dataReadBack1[1])) == 2.78);
+        TEST(dataReadBack1[2].type() ==  value::TYPE_STRING);
+        TEST(static_cast<string>(value_string(dataReadBack1[2])) == 
+             "hello world");
+
+        value val1(array1);
+        TEST(val1.type() == value::TYPE_ARRAY);
+        value_array array2(val1);
+        TEST(array2.size() == 3);
+        try {
+            value_array array4(value_int(4));
+            TEST_FAILED("invalid cast int-array suceeded");
+        } catch (error) {}
+    }
+};
+
+
+
+class valueTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "valueTestSuite";
+    }
+    virtual void runtests(unsigned int const indentation) {
+
+        intTestSuite().run(indentation+1);
+        doubleTestSuite().run(indentation+1);
+        booleanTestSuite().run(indentation+1);
+        datetimeTestSuite().run(indentation+1);
+        stringTestSuite().run(indentation+1);
+        bytestringTestSuite().run(indentation+1);
+        nilTestSuite().run(indentation+1);
+        structTestSuite().run(indentation+1);
+        arrayTestSuite().run(indentation+1);
+    }
+};
+
+
+namespace {
+string const noElementFoundXml(
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+    "<methodResponse>\r\n"
+    "<fault>\r\n"
+    "<value><struct>\r\n"
+    "<member><name>faultCode</name>\r\n"
+    "<value><i4>-503</i4></value></member>\r\n"
+    "<member><name>faultString</name>\r\n"
+    "<value><string>Call XML not a proper XML-RPC call.  "
+    "Call is not valid XML.  no element found</string></value>"
+    "</member>\r\n"
+    "</struct></value>\r\n"
+    "</fault>\r\n"
+    "</methodResponse>\r\n"
+    );
+
+string const sampleAddGoodCallXml(
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+    "<methodCall>\r\n"
+    "<methodName>sample.add</methodName>\r\n"
+    "<params>\r\n"
+    "<param><value><i4>5</i4></value></param>\r\n"
+    "<param><value><i4>7</i4></value></param>\r\n"
+    "</params>\r\n"
+    "</methodCall>\r\n"
+    );
+
+string const sampleAddGoodResponseXml(
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+    "<methodResponse>\r\n"
+    "<params>\r\n"
+    "<param><value><i4>12</i4></value></param>\r\n"
+    "</params>\r\n"
+    "</methodResponse>\r\n"
+    );
+
+
+string const sampleAddBadCallXml(
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+    "<methodCall>\r\n"
+    "<methodName>sample.add</methodName>\r\n"
+    "<params>\r\n"
+    "<param><value><i4>5</i4></value></param>\r\n"
+    "</params>\r\n"
+    "</methodCall>\r\n"
+    );
+
+string const sampleAddBadResponseXml(
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+    "<methodResponse>\r\n"
+    "<fault>\r\n"
+    "<value><struct>\r\n"
+    "<member><name>faultCode</name>\r\n"
+    "<value><i4>-501</i4></value></member>\r\n"
+    "<member><name>faultString</name>\r\n"
+    "<value><string>Not enough parameters</string></value></member>\r\n"
+    "</struct></value>\r\n"
+    "</fault>\r\n"
+    "</methodResponse>\r\n"
+    );
+
+
+string const nonexistentMethodCallXml(
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+    "<methodCall>\r\n"
+    "<methodName>nosuchmethod</methodName>\r\n"
+    "<params>\r\n"
+    "<param><value><i4>5</i4></value></param>\r\n"
+    "<param><value><i4>7</i4></value></param>\r\n"
+    "</params>\r\n"
+    "</methodCall>\r\n"
+    );
+
+string const nonexistentMethodYesDefResponseXml(
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+    "<methodResponse>\r\n"
+    "<params>\r\n"
+    "<param><value><string>no such method: nosuchmethod</string>"
+    "</value></param>\r\n"
+    "</params>\r\n"
+    "</methodResponse>\r\n"
+    );
+
+string const nonexistentMethodNoDefResponseXml(
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+    "<methodResponse>\r\n"
+    "<fault>\r\n"
+    "<value><struct>\r\n"
+    "<member><name>faultCode</name>\r\n"
+    "<value><i4>-506</i4></value></member>\r\n"
+    "<member><name>faultString</name>\r\n"
+    "<value><string>Method 'nosuchmethod' not defined</string></value>"
+    "</member>\r\n"
+    "</struct></value>\r\n"
+    "</fault>\r\n"
+    "</methodResponse>\r\n"
+    );
+
+} // namespace
+
+
+class paramListTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "paramListTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+
+        paramList paramList1;
+        TEST(paramList1.size() == 0);
+
+        paramList1.add(value_int(7));
+        paramList1.add(value_boolean(true));
+        paramList1.add(value_double(3.14));
+        time_t const timeZero(0);
+        paramList1.add(value_datetime(timeZero));
+        time_t const timeFuture(time(NULL)+100);
+        paramList1.add(value_datetime(timeFuture));
+        paramList1.add(value_string("hello world"));
+        unsigned char bytestringArray[] = {0x10, 0x11, 0x12, 0x13, 0x14};
+        vector<unsigned char> 
+            bytestringData(&bytestringArray[0], &bytestringArray[4]);
+        paramList1.add(value_bytestring(bytestringData));
+        vector<value> arrayData;
+        arrayData.push_back(value_int(7));
+        arrayData.push_back(value_double(2.78));
+        arrayData.push_back(value_string("hello world"));
+        paramList1.add(value_array(arrayData));
+        map<string, value> structData;
+        pair<string, value> member("the_integer", value_int(9));
+        structData.insert(member);
+        paramList1.add(value_struct(structData));
+        paramList1.add(value_nil());
+
+        TEST(paramList1.size() == 10);
+
+        TEST(paramList1.getInt(0) == 7);
+        TEST(paramList1.getInt(0, 7) == 7);
+        TEST(paramList1.getInt(0, -5, 7) == 7);
+        TEST(paramList1.getBoolean(1) == true);
+        TEST(paramList1.getDouble(2) == 3.14);
+        TEST(paramList1.getDouble(2, 1) == 3.14);
+        TEST(paramList1.getDouble(2, 1, 4) == 3.14);
+        TEST(paramList1.getDatetime_sec(3) == 0);
+        TEST(paramList1.getDatetime_sec(3, paramList::TC_ANY) == timeZero);
+        TEST(paramList1.getDatetime_sec(3, paramList::TC_NO_FUTURE) 
+             == timeZero);
+        TEST(paramList1.getDatetime_sec(4, paramList::TC_NO_PAST)
+             == timeFuture);
+        TEST(paramList1.getString(5) == "hello world");
+        TEST(paramList1.getBytestring(6)[0] == 0x10);
+        TEST(paramList1.getArray(7).size() == 3);
+        TEST(paramList1.getArray(7, 3).size() == 3);
+        TEST(paramList1.getArray(7, 1, 3).size() == 3);
+        paramList1.getStruct(8)["the_integer"];
+        paramList1.getNil(9);
+        paramList1.verifyEnd(10);
+
+        paramList paramList2(5);
+        TEST(paramList2.size() == 0);
+    }
+};
+
+class registryRegMethodTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "registryRegMethodTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+
+        xmlrpc_c::registry myRegistry;
+        
+        myRegistry.addMethod("sample.add", 
+                             xmlrpc_c::methodPtr(new sampleAddMethod));
+        
+        myRegistry.disableIntrospection();
+        {
+            string response;
+            myRegistry.processCall("", &response);
+            TEST(response == noElementFoundXml);
+        }
+        {
+            string response;
+            myRegistry.processCall(sampleAddGoodCallXml, &response);
+            TEST(response == sampleAddGoodResponseXml);
+        }
+        {
+            string response;
+            myRegistry.processCall(sampleAddBadCallXml, &response);
+            TEST(response == sampleAddBadResponseXml);
+        }
+    }
+};
+
+
+
+class registryDefaultMethodTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "registryDefaultMethodTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+
+        xmlrpc_c::registry myRegistry;
+        
+        myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+        {
+            string response;
+            myRegistry.processCall(sampleAddGoodCallXml, &response);
+            TEST(response == sampleAddGoodResponseXml);
+        }
+        {
+            string response;
+            myRegistry.processCall(nonexistentMethodCallXml, &response);
+            TEST(response == nonexistentMethodNoDefResponseXml);
+        }
+        // We're actually violating the spirit of setDefaultMethod by
+        // doing this to a registry that's already been used, but as long
+        // as it works, it's a convenient way to implement this test.
+        myRegistry.setDefaultMethod(defaultMethodPtr(new nameMethod));
+
+        {
+            string response;
+            myRegistry.processCall(nonexistentMethodCallXml, &response);
+            TEST(response == nonexistentMethodYesDefResponseXml);
+        }
+    }
+};
+
+
+
+class registryTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "registryTestSuite";
+    }
+    virtual void runtests(unsigned int const indentation) {
+
+        registryRegMethodTestSuite().run(indentation+1);
+        registryDefaultMethodTestSuite().run(indentation+1);
+    }
+};
+
+
+
+//=========================================================================
+//  Test Driver
+//=========================================================================
+
+int 
+main(int argc, char**) {
+    
+    int retval;
+
+    if (argc-1 > 0) {
+        cout << "Program takes no arguments" << endl;
+        exit(1);
+    }
+
+    bool testsPassed;
+
+    try {
+        // Add your test suites here.
+        valueTestSuite().run(0);
+        paramListTestSuite().run(0);
+        registryTestSuite().run(0);
+        serverAbyssTestSuite().run(0);
+        clientTestSuite().run(0);
+
+        testXmlRpcCpp();
+
+        testsPassed = true;
+    } catch (error const& error) {
+        cout << "Unexpected error thrown:  " << error.what() << endl;
+        testsPassed = false;
+    } catch (XmlRpcFault const& fault) {
+        cout << "Unexpected XML-RPC fault when running test suites." << endl
+             << "Fault #" << fault.getFaultCode()
+             << ": " << fault.getFaultString() << endl;
+        testsPassed = false;
+    } catch (...) {
+        cout << "Unexpected exception when running test suites." << endl;
+        testsPassed = false;
+    }
+
+    if (testsPassed) {
+        cout << "PASSED" << endl;
+        retval = 0;
+    } else {
+        cout << "FAILED" << endl;
+        retval = 1;
+    }
+    return retval;
+}
diff --git a/src/cpp/test/testclient.cpp b/src/cpp/test/testclient.cpp
new file mode 100644 (file)
index 0000000..affd1aa
--- /dev/null
@@ -0,0 +1,643 @@
+/*=============================================================================
+                                  testclient
+===============================================================================
+  Test the client C++ facilities of XML-RPC for C/C++.
+  
+  Contrary to what you might expect, we use the server facilities too
+  because we test of the client using a simulated server, via the
+  "direct" client XML transport we define herein.
+=============================================================================*/
+#include <string>
+#include <iostream>
+#include <vector>
+#include <sstream>
+#include <memory>
+#include <time.h>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "transport_config.h"
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/registry.hpp"
+#include "xmlrpc-c/client.hpp"
+#include "xmlrpc-c/client_simple.hpp"
+
+#include "tools.hpp"
+#include "testclient.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+
+
+class sampleAddMethod : public method {
+public:
+    sampleAddMethod() {
+        this->_signature = "i:ii";
+        this->_help = "This method adds two integers together";
+    }
+    void
+    execute(xmlrpc_c::paramList const& paramList,
+            value *             const  retvalP) {
+        
+        int const addend(paramList.getInt(0));
+        int const adder(paramList.getInt(1));
+        
+        paramList.verifyEnd(2);
+        
+        *retvalP = value_int(addend + adder);
+    }
+};
+
+
+
+class carriageParm_direct : public carriageParm {
+public:
+    carriageParm_direct(registry * const registryP) : registryP(registryP) {}
+
+    registry * registryP;
+};
+
+
+class clientXmlTransport_direct : public clientXmlTransport {
+
+public:    
+    void
+    call(xmlrpc_c::carriageParm * const  carriageParmP,
+         string                   const& callXml,
+         string *                 const  responseXmlP) {
+
+        carriageParm_direct * const parmP =
+            dynamic_cast<carriageParm_direct *>(carriageParmP);
+
+        if (parmP == NULL)
+            throw(error("Carriage parameter passed to the direct "
+                        "transport is not type carriageParm_direct"));
+
+        parmP->registryP->processCall(callXml, responseXmlP);
+    }
+};
+
+
+
+class clientDirectAsyncTestSuite : public testSuite {
+/*----------------------------------------------------------------------------
+   See clientDirectTestSuite for a description of how we use a
+   clientXmlTransport_direct object to test client functions.
+
+   The object of this class tests the async client functions.  With
+   clientXmlTransport_direct, these are pretty simple because the
+   transport doesn't even implement an asynchronous interface; it
+   relies on the base class' emulation of start() using call().
+
+   Some day, we should add true asynchronous capability to
+   clientXmlTransport_direct and really test things.
+-----------------------------------------------------------------------------*/
+public:
+    virtual string suiteName() {
+        return "clientDirectAsyncTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        
+        registry myRegistry;
+        
+        myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+        
+        carriageParm_direct carriageParmDirect(&myRegistry);
+        clientXmlTransport_direct transportDirect;
+        client_xml clientDirect(&transportDirect);
+        paramList paramListSampleAdd1;
+        paramListSampleAdd1.add(value_int(5));
+        paramListSampleAdd1.add(value_int(7));
+        paramList paramListSampleAdd2;
+        paramListSampleAdd2.add(value_int(30));
+        paramListSampleAdd2.add(value_int(-10));
+
+        rpcPtr const rpcSampleAdd1P("sample.add", paramListSampleAdd1);
+        rpcSampleAdd1P->start(&clientDirect, &carriageParmDirect);
+        rpcPtr const rpcSampleAdd2P("sample.add", paramListSampleAdd2);
+        rpcSampleAdd2P->start(&clientDirect, &carriageParmDirect);
+
+        TEST(rpcSampleAdd1P->isFinished());
+        TEST(rpcSampleAdd1P->isSuccessful());
+        value_int const result1(rpcSampleAdd1P->getResult());
+        TEST(static_cast<int>(result1) == 12);
+        
+        TEST(rpcSampleAdd2P->isFinished());
+        TEST(rpcSampleAdd1P->isSuccessful());
+        value_int const result2(rpcSampleAdd2P->getResult());
+        TEST(static_cast<int>(result2) == 20);
+
+        EXPECT_ERROR(clientDirect.finishAsync(timeout()););
+        EXPECT_ERROR(clientDirect.finishAsync(timeout(50)););
+    }
+};
+
+
+
+class clientDirectTestSuite : public testSuite {
+/*----------------------------------------------------------------------------
+  The object of this class tests the client facilities by using a
+  special client XML transport defined above and an XML-RPC server we
+  build ourselves and run inline.  We build the server out of a
+  xmlrpc_c::registry object and our transport just delivers XML
+  directly to the registry object and gets the response XML from it
+  and delivers that back.  There's no network or socket or pipeline or
+  anything -- the transport actually executes the XML-RPC method.
+-----------------------------------------------------------------------------*/
+public:
+    virtual string suiteName() {
+        return "clientDirectTestSuite";
+    }
+    virtual void runtests(unsigned int const indentation) {
+        registry myRegistry;
+        
+        myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+        
+        carriageParm_direct carriageParmDirect(&myRegistry);
+        clientXmlTransport_direct transportDirect;
+        client_xml clientDirect(&transportDirect);
+        paramList paramListSampleAdd;
+        paramListSampleAdd.add(value_int(5));
+        paramListSampleAdd.add(value_int(7));
+        paramList paramListEmpty;
+        {
+            /* Test a successful RPC */
+            rpcPtr rpcSampleAddP("sample.add", paramListSampleAdd);
+            rpcSampleAddP->call(&clientDirect, &carriageParmDirect);
+            TEST(rpcSampleAddP->isFinished());
+            TEST(rpcSampleAddP->isSuccessful());
+            value_int const resultDirect(rpcSampleAddP->getResult());
+            TEST(static_cast<int>(resultDirect) == 12);
+        }
+        {
+            /* Test a failed RPC */
+            rpcPtr const rpcSampleAddP("sample.add", paramListEmpty);
+            rpcSampleAddP->call(&clientDirect, &carriageParmDirect);
+            TEST(rpcSampleAddP->isFinished());
+            TEST(!rpcSampleAddP->isSuccessful());
+            fault const fault0(rpcSampleAddP->getFault());
+            TEST(fault0.getCode() == fault::CODE_TYPE);
+        }
+
+        {
+            /* Test with an auto object transport */
+            client_xml clientDirect(
+                clientXmlTransportPtr(new clientXmlTransport_direct));
+            rpcPtr rpcSampleAddP("sample.add", paramListSampleAdd);
+            rpcSampleAddP->call(&clientDirect, &carriageParmDirect);
+            TEST(rpcSampleAddP->isFinished());
+            TEST(rpcSampleAddP->isSuccessful());
+            EXPECT_ERROR(fault fault0(rpcSampleAddP->getFault()););
+            value_int const resultDirect(rpcSampleAddP->getResult());
+            TEST(static_cast<int>(resultDirect) == 12);
+        }
+        {
+            /* Test with implicit RPC -- success */
+            rpcOutcome outcome;
+            clientDirect.call(&carriageParmDirect, "sample.add",
+                              paramListSampleAdd, &outcome);
+            TEST(outcome.succeeded());
+            value_int const result(outcome.getResult());
+            TEST(static_cast<int>(result) == 12);
+        }
+        {
+            /* Test with implicit RPC - failure */
+            rpcOutcome outcome;
+            clientDirect.call(&carriageParmDirect, "nosuchmethod",
+                              paramList(), &outcome);
+            TEST(!outcome.succeeded());
+            TEST(outcome.getFault().getCode() == fault::CODE_NO_SUCH_METHOD);
+            TEST(outcome.getFault().getDescription().size() > 0);
+        }
+
+        clientDirectAsyncTestSuite().run(indentation+1);
+    }
+};
+
+
+
+class curlTransportTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "curlTransportTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+#if MUST_BUILD_CURL_CLIENT
+        clientXmlTransport_curl transport0;
+        clientXmlTransport_curl transport1("eth0");
+        clientXmlTransport_curl transport2("eth0", true);
+        clientXmlTransport_curl transport3("eth0", true, true);
+        clientXmlTransport_curl transport4(
+            clientXmlTransport_curl::constrOpt()
+            .network_interface("eth0")
+            .no_ssl_verifypeer(true)
+            .no_ssl_verifyhost(true)
+            .user_agent("my user agent")
+            .ssl_cert("/etc/sslcert")
+            .sslcerttype("PEM")
+            .sslcertpasswd("mypass")
+            .sslkey("/etc/sslkey")
+            .sslkeytype("DER")
+            .sslkeypasswd("mykeypass")
+            .sslengine("mysslengine")
+            .sslengine_default(true)
+            .sslversion(XMLRPC_SSLVERSION_SSLv2)
+            .cainfo("/etc/cainfo")
+            .capath("/etc/cadir")
+            .randomfile("/dev/random")
+            .egdsocket("/tmp/egdsocket")
+            .ssl_cipher_list("RC4-SHA:DEFAULT")
+            );            
+
+        clientXmlTransport_curl transport5(
+            clientXmlTransport_curl::constrOpt()
+            .no_ssl_verifypeer(false));
+
+        clientXmlTransport_curl transport6(
+            clientXmlTransport_curl::constrOpt());
+        
+        clientXmlTransportPtr transport1P(new clientXmlTransport_curl);
+        clientXmlTransportPtr transport2P;
+        transport2P = transport1P;
+#else
+        EXPECT_ERROR(clientXmlTransport_curl transport0;);
+        EXPECT_ERROR(clientXmlTransport_curl transport1("eth0"););
+        EXPECT_ERROR(clientXmlTransport_curl transport0("eth0", true););
+        EXPECT_ERROR(clientXmlTransport_curl transport0("eth0", true, true););
+#endif
+    }
+};
+
+
+
+class libwwwTransportTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "libwwwTransportTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+#if MUST_BUILD_LIBWWW_CLIENT
+        clientXmlTransport_libwww transport0;
+        clientXmlTransport_libwww transport1("getbent");
+        clientXmlTransport_libwww transport2("getbent", "1.0");
+        clientXmlTransportPtr transport1P(new clientXmlTransport_libwww);
+        clientXmlTransportPtr transport2P;
+        transport2P = transport1P;
+#else
+        EXPECT_ERROR(clientXmlTransport_libwww transport0;);
+        EXPECT_ERROR(clientXmlTransport_libwww transport1("getbent"););
+        EXPECT_ERROR(clientXmlTransport_libwww transport2("getbent", "1.0"););
+#endif
+    }
+};
+
+
+
+class wininetTransportTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "wininetTransportTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+#if MUST_BUILD_WININET_CLIENT
+        clientXmlTransport_wininet transport0;
+        clientXmlTransport_wininet transport1(true);
+        clientXmlTransportPtr transport1P(new clientXmlTransport_wininet);
+        clientXmlTransportPtr transport2P;
+        transport2P = transport1P;
+#else
+        EXPECT_ERROR(clientXmlTransport_wininet transport0;);
+        EXPECT_ERROR(clientXmlTransport_wininet transport1(true););
+#endif
+    }
+};
+
+
+
+class ambivalentTransportTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "ambivalentTransportTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+        vector<string> const typeList(
+            clientXmlTransport_http::availableTypes());
+
+        TEST(typeList.size() > 0);
+
+        clientXmlTransportPtr const transportP(
+            clientXmlTransport_http::create());
+        carriageParm_http0 carriageParm0("http://whatsamatta.edux");
+        client_xml client0(transportP);
+        
+        rpcOutcome outcome;
+
+        // Fails because there's no such server
+        EXPECT_ERROR(
+            client0.call(&carriageParm0, "nosuchmethod", paramList(),
+                         &outcome);
+            );
+    }
+};
+
+
+
+class clientXmlTransportTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "clientXmlTransportTestSuite";
+    }
+    virtual void runtests(unsigned int const indentation) {
+        curlTransportTestSuite().run(indentation + 1);
+        libwwwTransportTestSuite().run(indentation + 1);
+        wininetTransportTestSuite().run(indentation + 1);
+        ambivalentTransportTestSuite().run(indentation + 1);
+    }
+};
+
+
+
+class clientSimpleTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "clientSimpleTestSuite";
+    }
+    virtual void runtests(unsigned int const) {
+
+        clientSimple clientS0;
+        paramList paramList0;
+
+        value result0;
+
+        // These will fail because there's no such server
+        EXPECT_ERROR(clientS0.call("http://mf.comm", "biteme", &result0););
+
+        EXPECT_ERROR(
+            clientS0.call("http://mf.comm", "biteme", "s", &result0, "hard");
+            );
+
+        EXPECT_ERROR(
+            clientS0.call("http://mf.comm", "biteme", paramList0, &result0);
+            );
+    }
+};
+        
+
+
+class clientCurlTestSuite : public testSuite {
+/*----------------------------------------------------------------------------
+  The object of this class tests the combination of a client with
+  Curl transport.  We assume Curl transports themselves have already
+  been tested and clients with direct transports have already been tested.
+
+  We don't have an HTTP server, so we test only superficially.
+
+  In the future, we could either start a server or use some server that's
+  normally avaailble on the Internet.
+-----------------------------------------------------------------------------*/
+public:
+    virtual string suiteName() {
+        return "clientCurlTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+#if MUST_BUILD_CURL_CLIENT
+        clientXmlTransport_curl transportc0;
+        client_xml client0(&transportc0);
+        carriageParm_http0 carriageParmHttp("http://suckthis.com");
+        carriageParm_curl0 carriageParmCurl("http://suckthis.com");
+        connection connection0(&client0, &carriageParmHttp);
+        paramList paramList0;
+        
+        rpcOutcome outcome0;
+
+        // This fails because server doesn't exist
+        EXPECT_ERROR(
+            client0.call(&carriageParmHttp, "blowme", paramList0, &outcome0);
+                );
+
+        // This fails because server doesn't exist
+        EXPECT_ERROR(
+            client0.call(&carriageParmCurl, "blowme", paramList0, &outcome0);
+            );
+
+        rpcPtr rpc0P("blowme", paramList0);
+
+        // This fails because server doesn't exist
+        EXPECT_ERROR(rpc0P->call(&client0, &carriageParmCurl););
+
+        rpcPtr rpc1P("blowme", paramList0);
+        // This fails because server doesn't exist
+        EXPECT_ERROR(rpc1P->call(connection0););
+
+#else
+        // This fails because there is no Curl transport in the library.
+        EXPECT_ERROR(clientXmlTransport_curl transportc0;);
+#endif
+    }
+};
+
+
+
+class carriageParmTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "carriageParmTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+        carriageParm_http0 carriageParm1("http://suckthis.com");
+        carriageParm_curl0 carriageParm2("http://suckthis.com");
+        carriageParm_libwww0 carriageParm3("http://suckthis.com");
+        carriageParm_wininet0 carriageParm4("http://suckthis.com");
+
+        carriageParm_http0Ptr carriageParm_http1P(
+            new carriageParm_http0("http://suckthis.com"));
+
+        carriageParm_http1P->setBasicAuth("bryanh", "12345");
+
+        carriageParm_curl0Ptr carriageParm_curl1P(
+            new carriageParm_curl0("http://suckthis.com"));
+
+        carriageParm_curl1P->setBasicAuth("bryanh", "12345");
+
+        carriageParm_libwww0Ptr carriageParm_libwww1P(
+            new carriageParm_libwww0("http://suckthis.com"));
+
+        carriageParm_libwww1P->setBasicAuth("bryanh", "12345");
+
+        carriageParm_wininet0Ptr carriageParm_wininet1P(
+            new carriageParm_wininet0("http://suckthis.com"));
+
+        carriageParm_wininet1P->setBasicAuth("bryanh", "12345");
+    }
+};
+
+
+
+class clientRpcTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "clientRpcTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+
+        registry myRegistry;
+        
+        myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+        
+        carriageParm_direct carriageParm0(&myRegistry);
+        clientXmlTransport_direct transportDirect;
+        client_xml client0(&transportDirect);
+        paramList paramListSampleAdd;
+        paramListSampleAdd.add(value_int(5));
+        paramListSampleAdd.add(value_int(7));
+        paramList paramListEmpty;
+
+        {
+            /* Test a successful RPC */
+            rpcPtr rpcSampleAddP("sample.add", paramListSampleAdd);
+            TEST(!rpcSampleAddP->isFinished());
+            // This fails because RPC has not been executed
+            EXPECT_ERROR(value result(rpcSampleAddP->getResult()););
+            
+            rpcSampleAddP->call(&client0, &carriageParm0);
+
+            TEST(rpcSampleAddP->isFinished());
+            TEST(rpcSampleAddP->isSuccessful());
+            value_int const resultDirect(rpcSampleAddP->getResult());
+            TEST(static_cast<int>(resultDirect) == 12);
+            // This fails because the RPC succeeded
+            EXPECT_ERROR(fault fault0(rpcSampleAddP->getFault()););
+            // This fails because the RPC has already been executed
+            EXPECT_ERROR(
+                rpcSampleAddP->call(&client0, &carriageParm0););
+            // This fails because the RPC has already been executed
+            EXPECT_ERROR(
+                rpcSampleAddP->start(&client0, &carriageParm0););
+        }
+        {
+            /* Test a failed RPC */
+            rpcPtr const rpcSampleAddP("sample.add", paramListEmpty);
+            rpcSampleAddP->call(&client0, &carriageParm0);
+            TEST(rpcSampleAddP->isFinished());
+            TEST(!rpcSampleAddP->isSuccessful());
+            fault const fault0(rpcSampleAddP->getFault());
+            TEST(fault0.getCode() == fault::CODE_TYPE);
+            // This fails because the RPC failed
+            EXPECT_ERROR(value result(rpcSampleAddP->getResult()););
+            // This fails because the RPC has already been executed
+            EXPECT_ERROR(
+                rpcSampleAddP->call(&client0, &carriageParm0););
+            // This fails because the RPC has already been executed
+            EXPECT_ERROR(
+                rpcSampleAddP->start(&client0, &carriageParm0););
+        }
+        {
+            /* Test with a connection */
+
+            connection connection0(&client0, &carriageParm0);
+
+            rpcPtr const rpcSampleAddP("sample.add", paramListSampleAdd);
+
+            rpcSampleAddP->call(connection0);
+
+            TEST(rpcSampleAddP->isFinished());
+            value_int const resultDirect(rpcSampleAddP->getResult());
+            TEST(static_cast<int>(resultDirect) == 12);
+        }
+    }
+};
+
+
+
+class clientPtrTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "clientPtrTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+        registry myRegistry;
+        
+        myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+        carriageParm_direct carriageParmDirect(&myRegistry);
+        clientXmlTransport_direct transportDirect;
+        
+        clientPtr clientP(new client_xml(&transportDirect));
+
+        clientPtr client2P(clientP);
+
+        {
+            clientPtr client3P;
+            client3P = client2P;
+        }
+        rpcOutcome outcome;
+
+        clientP->call(&carriageParmDirect, "nosuchmethod",
+                      paramList(), &outcome);
+        TEST(!outcome.succeeded());
+        TEST(outcome.getFault().getCode() == fault::CODE_NO_SUCH_METHOD);
+    }
+};
+
+
+
+class serverAccessorTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "serverAccessorTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+        clientXmlTransportPtr const transportP(new clientXmlTransport_direct);
+        clientPtr const clientP(new client_xml(transportP));
+        registry myRegistry;
+        carriageParmPtr const carriageParmP(
+            new carriageParm_direct(&myRegistry));
+
+        serverAccessor server1(clientP, carriageParmP);
+
+        rpcOutcome outcome;
+        server1.call("nosuchmethod", paramList(), &outcome);
+        TEST(!outcome.succeeded());
+        TEST(outcome.getFault().getCode() == fault::CODE_NO_SUCH_METHOD);
+        TEST(outcome.getFault().getDescription().size() > 0);
+    }
+};
+
+
+
+string
+clientTestSuite::suiteName() {
+    return "clientTestSuite";
+}
+
+
+
+void
+clientTestSuite::runtests(unsigned int const indentation) {
+
+    clientDirectTestSuite().run(indentation+1);
+
+    clientXmlTransportTestSuite().run(indentation+1);
+    
+    carriageParmTestSuite().run(indentation+1);
+    
+    clientCurlTestSuite().run(indentation+1);
+
+    clientRpcTestSuite().run(indentation+1);
+    
+    clientPtrTestSuite().run(indentation+1);
+
+    clientSimpleTestSuite().run(indentation+1);
+
+    serverAccessorTestSuite().run(indentation+1);
+}
diff --git a/src/cpp/test/testclient.hpp b/src/cpp/test/testclient.hpp
new file mode 100644 (file)
index 0000000..20c1b9f
--- /dev/null
@@ -0,0 +1,9 @@
+#include "tools.hpp"
+
+class clientTestSuite : public testSuite {
+
+public:
+    virtual std::string suiteName();
+    virtual void runtests(unsigned int const indentation);
+};
+
diff --git a/src/cpp/test/testclient_dummy.cpp b/src/cpp/test/testclient_dummy.cpp
new file mode 100644 (file)
index 0000000..5bf3018
--- /dev/null
@@ -0,0 +1,29 @@
+/*=============================================================================
+                                  testclient_dummy
+===============================================================================
+  This is a substitute for testclient.cpp, for use in a test program that is
+  not linked with the client libraries.
+
+  It simply passes the test.
+=============================================================================*/
+
+#include <string>
+#include <iostream>
+
+#include "tools.hpp"
+#include "testclient.hpp"
+
+using namespace std;
+
+string
+clientTestSuite::suiteName() {
+    return "clientTestSuite";
+}
+
+
+void
+clientTestSuite::runtests(unsigned int const indentation) {
+
+    cout << string((indentation+1)*2, ' ') 
+         << "Running dummy test." << endl;
+}
diff --git a/src/cpp/test/tools.cpp b/src/cpp/test/tools.cpp
new file mode 100644 (file)
index 0000000..13728f9
--- /dev/null
@@ -0,0 +1,64 @@
+#include <string>
+#include <sstream>
+#include <iostream>
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+
+#include "tools.hpp"
+
+using namespace std;
+
+testSuite::~testSuite() {
+}
+
+
+
+void
+testSuite::run(unsigned int const indentation) {
+    try {
+        cout << string(indentation*2, ' ') 
+             << "Running " << suiteName() << endl;
+        this->runtests(indentation);
+    } catch (error const& error) {
+        throwf("%s failed.  %s", suiteName().c_str(), error.what());
+    } catch (...) {
+        throw(error(suiteName() + string(" failed.  ") +
+                    string("It threw an unexpected type of object")));
+    }
+    cout << string(indentation*2, ' ') 
+         << suiteName() << " tests passed." << endl;
+}
+
+
+
+// This is a good place to set a breakpoint.
+void 
+logFailedTest(const char * const fileName, 
+              unsigned int const lineNum, 
+              const char * const statement) {
+
+    ostringstream msg;
+
+    msg << endl
+        << fileName << ":" << lineNum 
+        << ": expected (" << statement << ")" << endl;
+
+    throw(error(msg.str()));
+}
+
+
+error
+fileLineError(string       const filename,
+              unsigned int const lineNumber,
+              string       const description) {
+    
+    ostringstream combined;
+    
+    combined << filename << ":" << lineNumber << " " << description;
+    
+    return error(combined.str());
+}
+
+
+
diff --git a/src/cpp/test/tools.hpp b/src/cpp/test/tools.hpp
new file mode 100644 (file)
index 0000000..a329b47
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef TEST_HPP_INCLUDED
+#define TEST_HPP_INCLUDED
+
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+
+class testSuite {
+/*----------------------------------------------------------------------------
+   This is a base class for a test suite.  Give the suite a name
+   (to be used in messages about it) and some test code via
+   virtual methods suiteName() and runtests(), respectively.
+
+   runtests() should throw either an 'error' object or an 'XmlRpcFault'
+   object if the test fails.  It should throw something else if the
+   test can't run.  It should throw nothing if the tests pass.
+
+   You don't normally keep an object of this class around.  You don't
+   even give it a name.  You simply refer to a literal object, like so:
+
+     myTestSuite().run(0)
+-----------------------------------------------------------------------------*/
+public:
+    virtual ~testSuite();
+
+    void run(unsigned int const indentation);
+
+    virtual void runtests(unsigned int const) {
+        throw(error("test suite does not have a runtests() method"));
+    };
+    virtual std::string suiteName() {
+        return "unnamed test suite";
+    }
+};
+
+
+
+void 
+logFailedTest(const char * const fileName, 
+              unsigned int const lineNum, 
+              const char * const statement);
+
+error
+fileLineError(std::string  const filename,
+              unsigned int const lineNumber,
+              std::string  const description);
+
+#define TEST(statement) \
+    do { \
+        if (!(statement)) \
+            logFailedTest(__FILE__, __LINE__, #statement); \
+    } while (0)
+
+
+#define TEST_PASSED() \
+    do { } while (0)
+
+#define TEST_FAILED(reason) \
+    do { \
+        logFailedTest(__FILE__, __LINE__, (reason)); \
+    } while (0)
+
+#define EXPECT_ERROR(statement) \
+    do { try { statement } catch (error) {break;} \
+      throw(fileLineError(__FILE__, __LINE__, "Didn't get expected error")); \
+    } while (0)
+
+#define trickToStraightenOutEmacsIndentation \
+;
+
+#endif
diff --git a/src/cpp/unix.make b/src/cpp/unix.make
new file mode 100644 (file)
index 0000000..cb7c69a
--- /dev/null
@@ -0,0 +1,23 @@
+# -*-makefile-*-    <-- an Emacs control
+
+# This is stuff for creating General case Unix shared libraries.
+# Some Unix systems can't use this.
+
+# This is to be included by 'Makefile'.  Most of the make variables here
+# come from the main make file.
+
+libxmlrpc_cpp.$(SHLIB_SUFFIX).$(MAJ).$(MIN): XmlRpcCpp.o
+       $(SHLIB_RULE)
+
+libxmlrpc++.$(SHLIB_SUFFIX).$(MAJ).$(MIN): $(LIBXMLRPCPP_OBJS)
+       $(SHLIB_RULE)
+
+libxmlrpc_server++.$(SHLIB_SUFFIX).$(MAJ).$(MIN): $(LIBXMLRPC_SERVERPP_OBJS)
+       $(SHLIB_RULE)
+
+libxmlrpc_server_abyss++.$(SHLIB_SUFFIX).$(MAJ).$(MIN): \
+  $(LIBXMLRPC_SERVER_ABYSSPP_OBJS)
+       $(SHLIB_RULE)
+
+libxmlrpc_client++.$(SHLIB_SUFFIX).$(MAJ).$(MIN): $(LIBXMLRPC_CLIENTPP_OBJS)
+       $(SHLIB_RULE)
diff --git a/src/cpp/value.cpp b/src/cpp/value.cpp
new file mode 100644 (file)
index 0000000..29457c0
--- /dev/null
@@ -0,0 +1,768 @@
+/*****************************************************************************
+                                value.cpp
+******************************************************************************
+  This module provides services for dealing with XML-RPC values.  Each
+  type of XML-RPC value is a C++ class.  An object represents a
+  particular XML-RPC value.
+
+  Everything is based on the C services in libxmlrpc.
+
+  We could make things more efficient by using the internal interfaces
+  via xmlrpc_int.h.  We could make them even more efficient by dumping
+  libxmlrpc altogether for some or all of these services.
+
+  An xmlrpc_c::value object is really just a handle for a C xmlrpc_value
+  object.  You're not supposed to make a pointer to an xmlrpc_c::value
+  object, but rather copy the object around.
+
+  Because the C xmlrpc_value object does reference counting, it
+  disappears automatically when the last handle does.  To go pure C++,
+  we'd have to have a C++ object for the value itself and a separate
+  handle object, like Boost's shared_ptr<>.
+
+  The C++ is designed so that the user never sees the C interface at
+  all.  Unfortunately, the user can see it if he wants because some
+  class members had to be declared public so that other components of
+  the library could see them, but the user is not supposed to access
+  those members.
+
+*****************************************************************************/
+
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include <time.h>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "env_wrap.hpp"
+
+#include "xmlrpc-c/base.hpp"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+namespace {
+
+void
+throwIfError(env_wrap const& env) {
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+}
+
+
+
+class cDatetimeValueWrapper {
+public:
+    xmlrpc_value * valueP;
+    
+    cDatetimeValueWrapper(time_t const cppvalue) {
+        env_wrap env;
+        
+        this->valueP = xmlrpc_datetime_new_sec(&env.env_c, cppvalue);
+        throwIfError(env);
+    }
+    ~cDatetimeValueWrapper() {
+        xmlrpc_DECREF(this->valueP);
+    }
+};
+
+
+class cStringWrapper {
+public:
+    const char * str;
+    size_t length;
+    cStringWrapper(xmlrpc_value * valueP) {
+        env_wrap env;
+
+        xmlrpc_read_string_lp(&env.env_c, valueP, &length, &str);
+        throwIfError(env);
+    }
+    ~cStringWrapper() {
+        free((char*)str);
+    }
+};
+
+
+
+} // namespace
+
+
+
+namespace xmlrpc_c {
+
+value::value() {
+    this->cValueP = NULL;
+}
+
+
+
+value::value(xmlrpc_value * const valueP) {  // default constructor
+
+    this->instantiate(valueP);
+}
+
+
+
+value::value(xmlrpc_c::value const& value) {  // copy constructor
+    this->cValueP = value.cValue();
+}
+
+
+
+xmlrpc_c::value&
+value::operator=(xmlrpc_c::value const& value) {
+
+    if (this->cValueP != NULL)
+        throw(error("Assigning to already instantiated xmlrpc_c::value"));
+
+    this->cValueP = value.cValue();
+    return *this;  // The result of the (a = b) expression
+}
+
+
+
+value::~value() {
+    if (this->cValueP) {
+        xmlrpc_DECREF(this->cValueP);
+    }
+}
+
+
+
+void
+value::instantiate(xmlrpc_value * const valueP) {
+
+    xmlrpc_INCREF(valueP);
+    this->cValueP = valueP;
+}
+
+
+
+xmlrpc_value *
+value::cValue() const {
+
+    if (this->cValueP) {
+        xmlrpc_INCREF(this->cValueP);  // For Caller
+    }
+    return this->cValueP;
+}
+
+
+
+void
+value::appendToCArray(xmlrpc_value * const arrayP) const {
+/*----------------------------------------------------------------------------
+  Append this value to the C array 'arrayP'.
+----------------------------------------------------------------------------*/
+    env_wrap env;
+
+    xmlrpc_array_append_item(&env.env_c, arrayP, this->cValueP);
+
+    throwIfError(env);
+}
+
+
+
+void
+value::addToCStruct(xmlrpc_value * const structP,
+                    string         const key) const {
+/*----------------------------------------------------------------------------
+  Add this value to the C array 'arrayP' with key 'key'.
+----------------------------------------------------------------------------*/
+    env_wrap env;
+
+    xmlrpc_struct_set_value_n(&env.env_c, structP,
+                              key.c_str(), key.length(),
+                              this->cValueP);
+
+    throwIfError(env);
+}
+
+
+
+value::type_t 
+value::type() const {
+    /* You'd think we could just cast from xmlrpc_type to
+       value:type_t, but Gcc warns if we do that.  So we have to do this
+       even messier union nonsense.
+    */
+    union {
+        xmlrpc_type   x;
+        value::type_t y;
+    } u;
+
+    u.x = xmlrpc_value_type(this->cValueP);
+
+    return u.y;
+}
+
+
+
+value_int::value_int(int const cppvalue) {
+
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper(int const cppvalue) {
+            env_wrap env;
+            
+            this->valueP = xmlrpc_int_new(&env.env_c, cppvalue);
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    cWrapper wrapper(cppvalue);
+    
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_int::value_int(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_INT)
+        throw(error("Not integer type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+value_int::operator int() const {
+
+    int retval;
+    env_wrap env;
+
+    xmlrpc_read_int(&env.env_c, this->cValueP, &retval);
+    throwIfError(env);
+
+    return retval;
+}
+
+
+
+value_double::value_double(double const cppvalue) {
+
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper(double const cppvalue) {
+            env_wrap env;
+            
+            this->valueP = xmlrpc_double_new(&env.env_c, cppvalue);
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    this->instantiate(cWrapper(cppvalue).valueP);
+}
+
+
+
+value_double::value_double(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_DOUBLE)
+        throw(error("Not double type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+value_double::operator double() const {
+
+    double retval;
+
+    env_wrap env;
+
+    xmlrpc_read_double(&env.env_c, this->cValueP, &retval);
+    throwIfError(env);
+
+    return retval;
+}
+
+
+
+value_boolean::value_boolean(bool const cppvalue) {
+
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper(xmlrpc_bool const cppvalue) {
+            env_wrap env;
+            
+            this->valueP = xmlrpc_bool_new(&env.env_c, cppvalue);
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    cWrapper wrapper(cppvalue);
+    
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_boolean::operator bool() const {
+
+    xmlrpc_bool retval;
+
+    env_wrap env;
+
+    xmlrpc_read_bool(&env.env_c, this->cValueP, &retval);
+    throwIfError(env);
+
+    return (bool)retval;
+}
+
+
+
+value_boolean::value_boolean(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_BOOLEAN)
+        throw(error("Not boolean type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+value_datetime::value_datetime(string const cppvalue) {
+
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper(string const cppvalue) {
+            env_wrap env;
+            
+            this->valueP = xmlrpc_datetime_new_str(&env.env_c,
+                                                   cppvalue.c_str());
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    cWrapper wrapper(cppvalue);
+    
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_datetime::value_datetime(time_t const cppvalue) {
+
+    cDatetimeValueWrapper wrapper(cppvalue);
+    
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_datetime::value_datetime(struct timeval const& cppvalue) {
+
+    cDatetimeValueWrapper wrapper(cppvalue.tv_sec);
+
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_datetime::value_datetime(struct timespec const& cppvalue) {
+
+    cDatetimeValueWrapper wrapper(cppvalue.tv_sec);
+
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_datetime::value_datetime(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_DATETIME)
+        throw(error("Not datetime type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+value_datetime::operator time_t() const {
+
+    time_t retval;
+    env_wrap env;
+
+    xmlrpc_read_datetime_sec(&env.env_c, this->cValueP, &retval);
+    throwIfError(env);
+
+    return retval;
+}
+
+
+
+value_string::value_string(string const& cppvalue) {
+    
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper(string const cppvalue) {
+            env_wrap env;
+            
+            this->valueP = xmlrpc_string_new(&env.env_c, cppvalue.c_str());
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    cWrapper wrapper(cppvalue);
+    
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_string::value_string(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_STRING)
+        throw(error("Not string type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+value_string::operator string() const {
+
+    env_wrap env;
+
+    cStringWrapper adapter(this->cValueP);
+
+    return string(adapter.str, adapter.length);
+}
+
+
+
+value_bytestring::value_bytestring(
+    vector<unsigned char> const& cppvalue) {
+
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper(vector<unsigned char> const& cppvalue) {
+            env_wrap env;
+            
+            this->valueP = 
+                xmlrpc_base64_new(&env.env_c, cppvalue.size(), &cppvalue[0]);
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    cWrapper wrapper(cppvalue);
+    
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+vector<unsigned char>
+value_bytestring::vectorUcharValue() const {
+
+    class cWrapper {
+    public:
+        const unsigned char * contents;
+        size_t length;
+
+        cWrapper(xmlrpc_value * const valueP) {
+            env_wrap env;
+
+            xmlrpc_read_base64(&env.env_c, valueP, &length, &contents);
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            free((void*)contents);
+        }
+    };
+    
+    cWrapper wrapper(this->cValueP);
+
+    return vector<unsigned char>(&wrapper.contents[0], 
+                                 &wrapper.contents[wrapper.length]);
+}
+
+
+
+size_t
+value_bytestring::length() const {
+
+    env_wrap env;
+    size_t length;
+
+    xmlrpc_read_base64_size(&env.env_c, this->cValueP, &length);
+    throwIfError(env);
+
+    return length;
+}
+
+
+
+value_bytestring::value_bytestring(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_BYTESTRING)
+        throw(error("Not byte string type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+value_array::value_array(vector<xmlrpc_c::value> const& cppvalue) {
+    
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper() {
+            env_wrap env;
+            
+            this->valueP = xmlrpc_array_new(&env.env_c);
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    cWrapper wrapper;
+    
+    vector<xmlrpc_c::value>::const_iterator i;
+    for (i = cppvalue.begin(); i != cppvalue.end(); ++i)
+        i->appendToCArray(wrapper.valueP);
+
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_array::value_array(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_ARRAY)
+        throw(error("Not array type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+vector<xmlrpc_c::value>
+value_array::vectorValueValue() const {
+
+    env_wrap env;
+
+    unsigned int arraySize;
+
+    arraySize = xmlrpc_array_size(&env.env_c, this->cValueP);
+    throwIfError(env);
+    
+    vector<xmlrpc_c::value> retval(arraySize);
+    
+    for (unsigned int i = 0; i < arraySize; ++i) {
+
+        class cWrapper {
+        public:
+            xmlrpc_value * valueP;
+
+            cWrapper(xmlrpc_value * const arrayP,
+                     unsigned int   const index) {
+                env_wrap env;
+
+                xmlrpc_array_read_item(&env.env_c, arrayP, index, &valueP);
+                
+                throwIfError(env);
+            }
+            ~cWrapper() {
+                xmlrpc_DECREF(valueP);
+            }
+        };
+
+        cWrapper wrapper(this->cValueP, i);
+
+        retval[i].instantiate(wrapper.valueP);
+    }
+
+    return retval;
+}
+
+
+
+size_t
+value_array::size() const {
+
+    env_wrap env;
+    unsigned int arraySize;
+
+    arraySize = xmlrpc_array_size(&env.env_c, this->cValueP);
+    throwIfError(env);
+    
+    return arraySize;
+}
+
+
+
+value_struct::value_struct(
+    map<string, xmlrpc_c::value> const &cppvalue) {
+
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper() {
+            env_wrap env;
+            
+            this->valueP = xmlrpc_struct_new(&env.env_c);
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    cWrapper wrapper;
+
+    map<string, xmlrpc_c::value>::const_iterator i;
+    for (i = cppvalue.begin(); i != cppvalue.end(); ++i) {
+        xmlrpc_c::value mapvalue(i->second);
+        string          mapkey(i->first);
+        mapvalue.addToCStruct(wrapper.valueP, mapkey);
+    }
+    
+    this->instantiate(wrapper.valueP);
+}
+
+
+
+value_struct::value_struct(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_STRUCT)
+        throw(error("Not struct type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+value_struct::operator map<string, xmlrpc_c::value>() const {
+
+    env_wrap env;
+    unsigned int structSize;
+
+    structSize = xmlrpc_struct_size(&env.env_c, this->cValueP);
+    throwIfError(env);
+    
+    map<string, xmlrpc_c::value> retval;
+    
+    for (unsigned int i = 0; i < structSize; ++i) {
+        class cMemberWrapper {
+        public:
+            xmlrpc_value * keyP;
+            xmlrpc_value * valueP;
+
+            cMemberWrapper(xmlrpc_value * const structP,
+                           unsigned int   const index) {
+
+                env_wrap env;
+            
+                xmlrpc_struct_read_member(&env.env_c, structP, index, 
+                                          &keyP, &valueP);
+                
+                throwIfError(env);
+            }
+            ~cMemberWrapper() {
+                xmlrpc_DECREF(keyP);
+                xmlrpc_DECREF(valueP);
+            }
+        };
+
+        cMemberWrapper memberWrapper(this->cValueP, i);
+
+        cStringWrapper keyWrapper(memberWrapper.keyP);
+
+        string const key(keyWrapper.str, keyWrapper.length);
+
+        retval[key] = xmlrpc_c::value(memberWrapper.valueP);
+    }
+
+    return retval;
+}
+
+
+
+value_nil::value_nil() {
+    
+    class cWrapper {
+    public:
+        xmlrpc_value * valueP;
+        
+        cWrapper() {
+            env_wrap env;
+            
+            this->valueP = xmlrpc_nil_new(&env.env_c);
+            throwIfError(env);
+        }
+        ~cWrapper() {
+            xmlrpc_DECREF(this->valueP);
+        }
+    };
+    
+    cWrapper wrapper;
+    
+    this->instantiate(wrapper.valueP);
+}
+    
+
+
+value_nil::value_nil(xmlrpc_c::value const baseValue) {
+
+    if (baseValue.type() != xmlrpc_c::value::TYPE_NIL)
+        throw(error("Not nil type.  See type() method"));
+    else {
+        this->instantiate(baseValue.cValueP);
+    }
+}
+
+
+
+} // namespace
+
diff --git a/src/cpp/wininet.cpp b/src/cpp/wininet.cpp
new file mode 100644 (file)
index 0000000..8a5a121
--- /dev/null
@@ -0,0 +1,168 @@
+/*=============================================================================
+                                wininet.cpp
+===============================================================================
+  This is the Wininet XML transport of the C++ XML-RPC client library for
+  Xmlrpc-c.
+=============================================================================*/
+
+#include <stdlib.h>
+#include <cassert>
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/girmem.hpp"
+using girmem::autoObjectPtr;
+using girmem::autoObject;
+#include "env_wrap.hpp"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/transport.h"
+#include "xmlrpc-c/base_int.h"
+
+#include "xmlrpc_wininet_transport.h"
+
+/* transport_config.h defines MUST_BUILD_WININET_CLIENT */
+#include "transport_config.h"
+
+#include "xmlrpc-c/client_transport.hpp"
+
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+class globalConstant {
+public:
+    globalConstant();
+    ~globalConstant();
+};
+
+
+
+globalConstant::globalConstant() {
+
+    // Not thread safe
+
+    xmlrpc_transport_setup setupFn;
+
+#if MUST_BUILD_WININET_CLIENT
+    setupFn = xmlrpc_wininet_transport_ops.setup_global_const;
+#else
+    setupFn = NULL;
+#endif
+    if (setupFn) {
+        env_wrap env;
+
+        setupFn(&env.env_c); // Not thread safe
+
+        if (env.env_c.fault_occurred)
+            throwf("Failed to do global initialization "
+                   "of Wininet transport code.  %s", env.env_c.fault_string);
+    }
+}
+
+
+
+globalConstant::~globalConstant() {
+
+    // Not thread safe
+
+    xmlrpc_transport_teardown teardownFn;
+
+#if MUST_BUILD_WININET_CLIENT
+    teardownFn = xmlrpc_wininet_transport_ops.teardown_global_const;
+#else
+    teardownFn = NULL;
+#endif
+    if (teardownFn)
+        teardownFn();  // not thread safe
+}
+
+
+
+globalConstant globalConst;
+    // This object is never accessed.  Its whole purpose to to be born and
+    // to die, which it does automatically as part of C++ program
+    // program initialization and termination.
+
+} // namespace
+
+
+namespace xmlrpc_c {
+
+carriageParm_wininet0::carriageParm_wininet0(
+    string const serverUrl
+    ) {
+
+    this->instantiate(serverUrl);
+}
+
+
+
+carriageParm_wininet0Ptr::carriageParm_wininet0Ptr() {
+    // Base class constructor will construct pointer that points to nothing
+}
+
+
+
+carriageParm_wininet0Ptr::carriageParm_wininet0Ptr(
+    carriageParm_wininet0 * const carriageParmP) {
+    this->point(carriageParmP);
+}
+
+
+
+carriageParm_wininet0 *
+carriageParm_wininet0Ptr::operator->() const {
+
+    autoObject * const p(this->objectP);
+    return dynamic_cast<carriageParm_wininet0 *>(p);
+}
+
+
+
+#if MUST_BUILD_WININET_CLIENT
+
+clientXmlTransport_wininet::clientXmlTransport_wininet(
+    bool const allowInvalidSslCerts
+    ) {
+
+    struct xmlrpc_wininet_xportparms transportParms; 
+
+    transportParms.allowInvalidSSLCerts = allowInvalidSslCerts;
+
+    this->c_transportOpsP = &xmlrpc_wininet_transport_ops;
+
+    env_wrap env;
+
+    xmlrpc_wininet_transport_ops.create(
+        &env.env_c, 0, "", "",
+        &transportParms, XMLRPC_WXPSIZE(allowInvalidSSLCerts),
+        &this->c_transportP);
+
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+}
+
+#else  // MUST_BUILD_WININET_CLIENT
+
+clientXmlTransport_wininet::clientXmlTransport_wininet(bool const) {
+
+    throw(error("There is no Wininet client XML transport "
+                "in this XML-RPC client library"));
+}
+
+#endif
+
+
+clientXmlTransport_wininet::~clientXmlTransport_wininet() {
+
+    this->c_transportOpsP->destroy(this->c_transportP);
+}
+
+} // namespace
diff --git a/src/cpp/xml.cpp b/src/cpp/xml.cpp
new file mode 100644 (file)
index 0000000..b76339b
--- /dev/null
@@ -0,0 +1,168 @@
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/base.hpp"
+#include "env_wrap.hpp"
+
+#include "xmlrpc-c/xml.hpp"
+
+using namespace std;
+using namespace xmlrpc_c;
+
+
+namespace {
+
+class cValueWrapper {
+/*----------------------------------------------------------------------------
+   Use an object of this class to set up to remove a reference to an
+   xmlrpc_value object (a C object with manual reference management)
+   at then end of a scope -- even if the scope ends with a throw.
+-----------------------------------------------------------------------------*/
+public:
+    xmlrpc_value * valueP;
+    cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {}
+    ~cValueWrapper() { xmlrpc_DECREF(valueP); }
+};
+
+xmlrpc_value *
+cArrayFromParamList(paramList const& paramList) {
+
+    env_wrap env;
+
+    xmlrpc_value * paramArrayP;
+
+    paramArrayP = xmlrpc_array_new(&env.env_c);
+    if (!env.env_c.fault_occurred) {
+        for (unsigned int i = 0;
+             i < paramList.size() && !env.env_c.fault_occurred;
+             ++i) {
+            cValueWrapper const param(paramList[i].cValue());
+
+            xmlrpc_array_append_item(&env.env_c, paramArrayP, param.valueP);
+        }
+    }
+    if (env.env_c.fault_occurred) {
+        xmlrpc_DECREF(paramArrayP);
+        throw(error(env.env_c.fault_string));
+    }
+    return paramArrayP;
+}
+
+} // namespace
+
+
+namespace xmlrpc_c {
+namespace xml {
+
+
+void
+generateCall(string    const& methodName,
+             paramList const& paramList,
+             string *  const  callXmlP) {
+/*----------------------------------------------------------------------------
+   Generate the XML for an XML-RPC call, given a method name and parameter
+   list.
+-----------------------------------------------------------------------------*/
+    class memblockWrapper {
+        xmlrpc_mem_block * const memblockP;
+    public:
+        memblockWrapper(xmlrpc_mem_block * const memblockP) :
+            memblockP(memblockP) {}
+
+        ~memblockWrapper() {
+            XMLRPC_MEMBLOCK_FREE(char, memblockP);
+        }
+    };
+
+    xmlrpc_mem_block * callXmlMP;
+    env_wrap env;
+
+    callXmlMP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0);
+    if (!env.env_c.fault_occurred) {
+        memblockWrapper callXmlHolder(callXmlMP);
+            // Makes callXmlMP get freed at end of scope
+
+        xmlrpc_value * const paramArrayP(cArrayFromParamList(paramList));
+
+        xmlrpc_serialize_call(&env.env_c, callXmlMP, methodName.c_str(),
+                              paramArrayP);
+        
+        *callXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, callXmlMP),
+                           XMLRPC_MEMBLOCK_SIZE(char, callXmlMP));
+        
+        xmlrpc_DECREF(paramArrayP);
+    }
+    if (env.env_c.fault_occurred)
+        throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+parseResponse(string       const& responseXml,
+              rpcOutcome * const  outcomeP) {
+/*----------------------------------------------------------------------------
+   Parse the XML for an XML-RPC response into an XML-RPC result value.
+-----------------------------------------------------------------------------*/
+    env_wrap env;
+
+    xmlrpc_value * c_resultP;
+    int faultCode;
+    const char * faultString;
+
+    xmlrpc_parse_response2(&env.env_c, responseXml.c_str(), responseXml.size(),
+                           &c_resultP, &faultCode, &faultString);
+
+    if (env.env_c.fault_occurred)
+        throwf("Unable to find XML-RPC response in what server sent back.  %s",
+               env.env_c.fault_string);
+    else {
+        if (faultString) {
+            *outcomeP =
+                rpcOutcome(fault(faultString,
+                                 static_cast<fault::code_t>(faultCode)));
+            xmlrpc_strfree(faultString);
+        } else {
+            XMLRPC_ASSERT_VALUE_OK(c_resultP);
+            *outcomeP = rpcOutcome(value(c_resultP));
+            xmlrpc_DECREF(c_resultP);
+        }
+    }
+}
+
+
+
+void
+parseSuccessfulResponse(string  const& responseXml,
+                        value * const  resultP) {
+/*----------------------------------------------------------------------------
+   Same as parseResponse(), but expects the response to indicate success;
+   throws an error if it doesn't.
+-----------------------------------------------------------------------------*/
+    rpcOutcome outcome;
+
+    parseResponse(responseXml, &outcome);
+
+    if (!outcome.succeeded())
+        throwf("RPC response indicates it failed.  %s",
+               outcome.getFault().getDescription().c_str());
+
+    *resultP = outcome.getResult();
+}
+
+
+
+void
+trace(string const& label,
+      string const& xml) {
+    
+    xmlrpc_traceXml(label.c_str(), xml.c_str(), xml.size());
+
+}
+
+
+}} // namespace
diff --git a/src/registry.c b/src/registry.c
new file mode 100644 (file)
index 0000000..5497861
--- /dev/null
@@ -0,0 +1,492 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "system_method.h"
+
+#include "registry.h"
+
+/*=========================================================================
+  XML-RPC Server Method Registry
+===========================================================================
+  A method registry is a list of XML-RPC methods for a server to
+  implement, along with the details of how to implement each -- most
+  notably a function pointer for a function that executes the method.
+
+  To build an XML-RPC server, just add a communication facility.
+
+  The registry object consists principally of an xmlrpc_value.  That
+  xmlrpc_value is a struct, with method name as key.  Each value in
+  the struct a "method info" array.  A method info array has the
+  following items:
+
+     0: cptr: method function ptr
+     1: cptr: user data
+     2: array: signature list
+     3: string: help text.
+    
+  The signature list array contains one item for each form of call (a
+  single method might have multiple forms, e.g. one takes two integer
+  arguments; another takes a single string).  The array for each form
+  represents a signature.  It has an item for each parameter and one
+  for the result.  Item 0 is for the result, the rest are in order of
+  the parameters.  Each item of that array is the name of the XML-RPC
+  element that represents that type, e.g.  "int" or
+  "dateTime.iso8601".
+
+  Example signature:
+
+    (("int"
+      "double"
+      "double"
+     )
+     ("int"
+     )
+    )
+
+  The signature list array is empty to indicate that there is no signature
+  information in the registry (it doesn't mean there are no valid forms
+  of calling the method -- just that the registry declines to state).
+
+
+  WARNING: there's a basic problem with using xmlrpc_value objects to
+  represent the registry: xmlrpc_value objects are defined to be not
+  thread-safe: you can't use one from two threads at the same time.
+  But XML-RPC servers are often threaded, with multiple threads
+  simultaneously executing multiple RPCs.  The normal Xmlrpc-c Abyss
+  server is a good example.
+
+  As a hack to make this work, we use the old, deprecated "get"
+  functions that don't take a reference in the call dispatching code.
+  Maintaining the reference count is the only way that the the
+  thread-unsafety can manifest itself in our application.  Since the
+  registry has at least one reference to each xmlrpc_value as long as
+  the registry exists, we don't really need the exact reference count,
+  so the deprecated functions work fine.
+
+=========================================================================*/
+
+
+
+xmlrpc_registry *
+xmlrpc_registry_new(xmlrpc_env * const envP) {
+
+    xmlrpc_registry * registryP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    
+    MALLOCVAR(registryP);
+
+    if (registryP == NULL)
+        xmlrpc_faultf(envP, "Could not allocate memory for registry");
+    else {
+        registryP->_introspection_enabled = true;
+        registryP->_default_method        = NULL;
+        registryP->_preinvoke_method      = NULL;
+        registryP->_shutdown_server_fn    = NULL;
+
+        registryP->_methods = xmlrpc_struct_new(envP);
+        if (!envP->fault_occurred) {
+            xmlrpc_installSystemMethods(envP, registryP);
+        }    
+        if (envP->fault_occurred)
+            free(registryP);
+    }
+    return registryP;
+}
+
+
+
+void 
+xmlrpc_registry_free(xmlrpc_registry * const registryP) {
+
+    XMLRPC_ASSERT_PTR_OK(registryP);
+    XMLRPC_ASSERT(registryP->_methods != XMLRPC_BAD_POINTER);
+
+    xmlrpc_DECREF(registryP->_methods);
+
+    if (registryP->_default_method != NULL)
+        xmlrpc_DECREF(registryP->_default_method);
+
+    if (registryP->_preinvoke_method != NULL)
+        xmlrpc_DECREF(registryP->_preinvoke_method);
+
+    free(registryP);
+}
+
+
+
+void 
+xmlrpc_registry_add_method_w_doc(
+    xmlrpc_env *      const envP,
+    xmlrpc_registry * const registryP,
+    const char *      const host ATTR_UNUSED,
+    const char *      const methodName,
+    xmlrpc_method     const method,
+    void *            const userData,
+    const char *      const signatureString,
+    const char *      const help) {
+
+    const char * const helpString =
+        help ? help : "No help is available for this method.";
+
+    xmlrpc_env env;
+    xmlrpc_value * signatureListP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(registryP);
+    XMLRPC_ASSERT(host == NULL);
+    XMLRPC_ASSERT_PTR_OK(methodName);
+    XMLRPC_ASSERT_PTR_OK(method);
+
+    xmlrpc_env_init(&env);
+
+    xmlrpc_buildSignatureArray(&env, signatureString, &signatureListP);
+    if (env.fault_occurred)
+        xmlrpc_faultf(envP, "Can't interpret signature string '%s'.  %s",
+                      signatureString, env.fault_string);
+    else {
+        xmlrpc_value * methodInfoP;
+
+        XMLRPC_ASSERT_VALUE_OK(signatureListP);
+
+        methodInfoP = xmlrpc_build_value(envP, "(ppVs)", (void*) method,
+                                         userData, signatureListP, helpString);
+        if (!envP->fault_occurred) {
+            xmlrpc_struct_set_value(envP, registryP->_methods,
+                                    methodName, methodInfoP);
+
+            xmlrpc_DECREF(methodInfoP);
+        }
+        xmlrpc_DECREF(signatureListP);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void 
+xmlrpc_registry_add_method(xmlrpc_env *env,
+                           xmlrpc_registry *registry,
+                           const char *host,
+                           const char *method_name,
+                           xmlrpc_method method,
+                           void *user_data) {
+
+    xmlrpc_registry_add_method_w_doc (env, registry, host, method_name,
+                      method, user_data, "?",
+                      "No help is available for this method.");
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_registry_set_default_method
+**=========================================================================
+**  See xmlrpc.h for more documentation.
+*/
+
+void 
+xmlrpc_registry_set_default_method(xmlrpc_env *env,
+                                   xmlrpc_registry *registry,
+                                   xmlrpc_default_method handler,
+                                   void *user_data) {
+    xmlrpc_value *method_info;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_PTR_OK(registry);
+    XMLRPC_ASSERT_PTR_OK(handler);
+
+    /* Error-handling preconditions. */
+    method_info = NULL;
+    
+    /* Store our method and user data into our hash table. */
+    method_info = xmlrpc_build_value(env, "(pp)", (void*) handler, user_data);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Dispose of any pre-existing default method and install ours. */
+    if (registry->_default_method)
+        xmlrpc_DECREF(registry->_default_method);
+    registry->_default_method = method_info;
+    
+cleanup:
+    if (env->fault_occurred) {
+        if (method_info)
+            xmlrpc_DECREF(method_info);
+    }
+}
+
+
+
+
+void 
+xmlrpc_registry_set_preinvoke_method(xmlrpc_env *env,
+                                     xmlrpc_registry *registry,
+                                     xmlrpc_preinvoke_method handler,
+                                     void *user_data) {
+    xmlrpc_value *method_info;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_PTR_OK(registry);
+    XMLRPC_ASSERT_PTR_OK(handler);
+
+    /* Error-handling preconditions. */
+    method_info = NULL;
+
+    /* Store our method and user data into our hash table. */
+    method_info = xmlrpc_build_value(env, "(pp)", (void*) handler, user_data);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Dispose of any pre-existing preinvoke method and install ours. */
+    if (registry->_preinvoke_method)
+        xmlrpc_DECREF(registry->_preinvoke_method);
+    registry->_preinvoke_method = method_info;
+
+ cleanup:
+    if (env->fault_occurred) {
+        if (method_info)
+            xmlrpc_DECREF(method_info);
+    }
+}
+
+
+
+void
+xmlrpc_registry_set_shutdown(xmlrpc_registry *           const registryP,
+                             xmlrpc_server_shutdown_fn * const shutdownFn,
+                             void *                      const context) {
+
+    XMLRPC_ASSERT_PTR_OK(registryP);
+    XMLRPC_ASSERT_PTR_OK(shutdownFn);
+
+    registryP->_shutdown_server_fn = shutdownFn;
+
+    registryP->_shutdown_context = context;
+}
+
+
+
+/*=========================================================================
+**  dispatch_call
+**=========================================================================
+**  An internal method which actually does the dispatch. This may get
+**  prettified and exported at some point in the future.
+*/
+
+static void
+callPreinvokeMethodIfAny(xmlrpc_env *      const envP,
+                         xmlrpc_registry * const registryP,
+                         const char *      const methodName,
+                         xmlrpc_value *    const paramArrayP) {
+
+    /* Get the preinvoke method, if it is set. */
+    if (registryP->_preinvoke_method) {
+        xmlrpc_preinvoke_method preinvoke_method;
+        void * user_data;
+
+        xmlrpc_parse_value(envP, registryP->_preinvoke_method, "(pp)",
+                           &preinvoke_method, &user_data);
+        if (!envP->fault_occurred)
+            (*preinvoke_method)(envP, methodName,
+                                paramArrayP, user_data);
+    }
+}
+
+
+
+static void
+callDefaultMethod(xmlrpc_env *    const envP,
+                  xmlrpc_value *  const defaultMethodInfo,
+                  const char *    const methodName,
+                  xmlrpc_value *  const paramArrayP,
+                  xmlrpc_value ** const resultPP) {
+
+    xmlrpc_default_method default_method;
+    void * user_data;
+
+    xmlrpc_parse_value(envP, defaultMethodInfo, "(pp)",
+                       &default_method, &user_data);
+
+    if (!envP->fault_occurred)
+        *resultPP = (*default_method)(envP, NULL, methodName,
+                                      paramArrayP, user_data);
+}
+    
+
+
+static void
+callNamedMethod(xmlrpc_env *    const envP,
+                xmlrpc_value *  const methodInfo,
+                xmlrpc_value *  const paramArrayP,
+                xmlrpc_value ** const resultPP) {
+
+    xmlrpc_method method;
+    void * user_data;
+    
+    xmlrpc_parse_value(envP, methodInfo, "(pp*)", &method, &user_data);
+    if (!envP->fault_occurred)
+        *resultPP = (*method)(envP, paramArrayP, user_data);
+}
+
+
+
+void
+xmlrpc_dispatchCall(xmlrpc_env *      const envP, 
+                    xmlrpc_registry * const registryP,
+                    const char *      const methodName, 
+                    xmlrpc_value *    const paramArrayP,
+                    xmlrpc_value **   const resultPP) {
+
+    callPreinvokeMethodIfAny(envP, registryP, methodName, paramArrayP);
+    if (!envP->fault_occurred) {
+        xmlrpc_value * methodInfoP;
+        xmlrpc_env methodLookupEnv;
+
+        xmlrpc_env_init(&methodLookupEnv);
+
+        /* See comments at top of file about why we use the deprecated
+           xmlrpc_struct_get_value() here
+        */
+        methodInfoP = xmlrpc_struct_get_value(&methodLookupEnv,
+                                              registryP->_methods,
+                                              methodName);
+        if (!methodLookupEnv.fault_occurred)
+            callNamedMethod(envP, methodInfoP, paramArrayP, resultPP);
+        else if (methodLookupEnv.fault_code == XMLRPC_INDEX_ERROR) {
+            if (registryP->_default_method)
+                callDefaultMethod(envP, registryP->_default_method, 
+                                  methodName, paramArrayP,
+                                  resultPP);
+            else {
+                /* No matching method, and no default. */
+                xmlrpc_env_set_fault_formatted(
+                    envP, XMLRPC_NO_SUCH_METHOD_ERROR,
+                    "Method '%s' not defined", methodName);
+            }
+        } else
+            xmlrpc_faultf(envP, "failed to lookup method in registry's "
+                          "internal method struct.  %s",
+                          methodLookupEnv.fault_string);
+        xmlrpc_env_clean(&methodLookupEnv); 
+    }
+    /* For backward compatibility, for sloppy users: */
+    if (envP->fault_occurred)
+        *resultPP = NULL;
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_registry_process_call
+**=========================================================================
+**
+*/
+
+xmlrpc_mem_block *
+xmlrpc_registry_process_call(xmlrpc_env *      const envP,
+                             xmlrpc_registry * const registryP,
+                             const char *      const host ATTR_UNUSED,
+                             const char *      const xml_data,
+                             size_t            const xml_len) {
+
+    xmlrpc_mem_block * output;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(xml_data);
+    
+    xmlrpc_traceXml("XML-RPC CALL", xml_data, xml_len);
+
+    /* Allocate our output buffer.
+    ** If this fails, we need to die in a special fashion. */
+    output = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+    if (!envP->fault_occurred) {
+        const char * methodName;
+        xmlrpc_value * paramArray;
+        xmlrpc_env fault;
+        xmlrpc_env parseEnv;
+
+        xmlrpc_env_init(&fault);
+        xmlrpc_env_init(&parseEnv);
+
+        xmlrpc_parse_call(&parseEnv, xml_data, xml_len, 
+                          &methodName, &paramArray);
+
+        if (parseEnv.fault_occurred)
+            xmlrpc_env_set_fault_formatted(
+                &fault, XMLRPC_PARSE_ERROR,
+                "Call XML not a proper XML-RPC call.  %s",
+                parseEnv.fault_string);
+        else {
+            xmlrpc_value * result;
+            
+            xmlrpc_dispatchCall(&fault, registryP, methodName, paramArray,
+                                &result);
+
+            if (!fault.fault_occurred) {
+                xmlrpc_serialize_response(envP, output, result);
+
+                /* A comment here used to say that
+                   xmlrpc_serialize_response() could fail and "leave
+                   stuff in the buffer."  Don't know what that means,
+                   but it sounds like something that needs to be
+                   fixed.  The old code aborted the program here if
+                   xmlrpc_serialize_repsonse() failed.  04.11.17 
+                */
+                xmlrpc_DECREF(result);
+            } 
+            xmlrpc_strfree(methodName);
+            xmlrpc_DECREF(paramArray);
+        }
+        if (!envP->fault_occurred && fault.fault_occurred)
+            xmlrpc_serialize_fault(envP, output, &fault);
+
+        xmlrpc_env_clean(&parseEnv);
+        xmlrpc_env_clean(&fault);
+
+        if (envP->fault_occurred)
+            XMLRPC_MEMBLOCK_FREE(char, output);
+        else
+            xmlrpc_traceXml("XML-RPC RESPONSE", 
+                            XMLRPC_MEMBLOCK_CONTENTS(char, output),
+                            XMLRPC_MEMBLOCK_SIZE(char, output));
+    }
+    return output;
+}
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2001 by Eric Kidd. All rights reserved.
+** Copyright (C) 2001 by Luke Howard. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/src/registry.h b/src/registry.h
new file mode 100644 (file)
index 0000000..6e1fa50
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef REGISTRY_H_INCLUDED
+#define REGISTRY_H_INCLUDED
+
+#include "bool.h"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+
+struct _xmlrpc_registry {
+    bool           _introspection_enabled;
+    xmlrpc_value * _methods;
+    xmlrpc_value * _default_method;
+    xmlrpc_value * _preinvoke_method;
+    xmlrpc_server_shutdown_fn * _shutdown_server_fn;
+        /* Function that can be called to shut down the server that is
+           using this registry.  NULL if none.
+        */
+    void * _shutdown_context;
+        /* Context for _shutdown_server_fn -- understood only by
+           that function, passed to it as argument.
+        */
+};
+
+void
+xmlrpc_dispatchCall(struct _xmlrpc_env *      const envP, 
+                    struct _xmlrpc_registry * const registryP,
+                    const char *              const methodName, 
+                    struct _xmlrpc_value *    const paramArrayP,
+                    struct _xmlrpc_value **   const resultPP);
+
+#endif
diff --git a/src/system_method.c b/src/system_method.c
new file mode 100644 (file)
index 0000000..0487c53
--- /dev/null
@@ -0,0 +1,807 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "registry.h"
+
+#include "system_method.h"
+
+
+struct systemMethodReg {
+/*----------------------------------------------------------------------------
+   Information needed to register a system method
+-----------------------------------------------------------------------------*/
+    const char *  const methodName;
+    xmlrpc_method const methodFunction;
+    const char *  const signatureString;
+    const char *  const helpText;
+};
+
+
+
+void 
+xmlrpc_registry_disable_introspection(xmlrpc_registry * const registryP) {
+
+    XMLRPC_ASSERT_PTR_OK(registryP);
+
+    registryP->_introspection_enabled = false;
+}
+
+
+
+static void
+translateTypeSpecifierToName(xmlrpc_env *  const envP,
+                             char          const typeSpecifier,
+                             const char ** const typeNameP) {
+
+    switch (typeSpecifier) {
+    case 'i': *typeNameP = "int";              break;
+    case 'b': *typeNameP = "boolean";          break;
+    case 'd': *typeNameP = "double";           break;
+    case 's': *typeNameP = "string";           break;
+    case '8': *typeNameP = "dateTime.iso8601"; break;
+    case '6': *typeNameP = "base64";           break;
+    case 'S': *typeNameP = "struct";           break;
+    case 'A': *typeNameP = "array";            break;
+    case 'n': *typeNameP = "nil";              break;
+    default:
+        xmlrpc_faultf(envP, 
+                      "Method registry contains invalid signature "
+                      "data.  It contains the type specifier '%c'",
+                      typeSpecifier);
+    }
+}
+                
+
+
+static void
+parseOneTypeSpecifier(xmlrpc_env *   const envP,
+                      const char *   const startP,
+                      xmlrpc_value * const signatureP,
+                      const char **  const nextP) {
+/*----------------------------------------------------------------------------
+   Parse one type specifier at 'startP' within a signature string.
+
+   Add the appropriate item for it to the array 'signatureP'.
+
+   Return as *nextP the location the signature string just past the
+   type specifier, and also past the colon that comes after the 
+   type specifier for a return value.
+-----------------------------------------------------------------------------*/
+    const char * typeName;
+    const char * cursorP;
+
+    cursorP = startP;
+                
+    translateTypeSpecifierToName(envP, *cursorP, &typeName);
+    
+    if (!envP->fault_occurred) {
+        xmlrpc_value * typeP;
+        int sigArraySize;
+        
+        /* Append the appropriate string to the signature. */
+        typeP = xmlrpc_string_new(envP, typeName);
+        xmlrpc_array_append_item(envP, signatureP, typeP);
+        xmlrpc_DECREF(typeP);
+        
+        ++cursorP; /* move past the type specifier */
+        
+        sigArraySize = xmlrpc_array_size(envP, signatureP);
+        if (!envP->fault_occurred) {
+            if (sigArraySize == 1) {
+                /* We parsed off the result type, so we should now
+                   see the colon that separates the result type from
+                   the parameter types
+                */
+                if (*cursorP != ':')
+                    xmlrpc_faultf(envP, "No colon (':') after "
+                                  "the result type specifier");
+                else
+                    ++cursorP;
+            }
+        }
+    }
+    *nextP = cursorP;
+}
+
+
+
+static void
+parseOneSignature(xmlrpc_env *    const envP,
+                  const char *    const startP,
+                  xmlrpc_value ** const signaturePP,
+                  const char **   const nextP) {
+/*----------------------------------------------------------------------------
+   Parse one signature from the signature string that starts at 'startP'.
+
+   Return that signature as an array xmlrpc_value pointer
+   *signaturePP.  The array has one element for the return value,
+   followed by one element for each parameter described in the
+   signature.  That element is a string naming the return value or
+   parameter type, e.g. "int".
+
+   Return as *nextP the location in the signature string of the next
+   signature (i.e. right after the next comma).  If there is no next
+   signature (the string ends before any comma), make it point to the
+   terminating NUL.
+-----------------------------------------------------------------------------*/
+    xmlrpc_value * signatureP;
+
+    signatureP = xmlrpc_array_new(envP);  /* Start with empty array */
+    if (!envP->fault_occurred) {
+        const char * cursorP;
+
+        cursorP = startP;  /* start at the beginning */
+
+        while (!envP->fault_occurred && *cursorP != ',' && *cursorP != '\0')
+            parseOneTypeSpecifier(envP, cursorP, signatureP, &cursorP);
+
+        if (!envP->fault_occurred) {
+            if (xmlrpc_array_size(envP, signatureP) < 1)
+                xmlrpc_faultf(envP, "empty signature (a signature "
+                              "must have at least  return value type)");
+            if (*cursorP != '\0') {
+                assert(*cursorP == ',');
+                ++cursorP;
+            }
+            *nextP = cursorP;
+        }
+        if (envP->fault_occurred)
+            xmlrpc_DECREF(signatureP);
+        else
+            *signaturePP = signatureP;
+    }
+}    
+
+
+
+void
+xmlrpc_buildSignatureArray(xmlrpc_env *    const envP,
+                           const char *    const sigListString,
+                           xmlrpc_value ** const resultPP) {
+/*----------------------------------------------------------------------------
+  Turn the signature string 'sig' (e.g. "ii,s") into an array
+  as *resultP.  The array contains one element for each signature in
+  the string.  (Signatures are separated by commas.  The "ii,s" example
+  is two signatures: "ii" and "s").  Each element is itself an array
+  as described under parseOneSignature().
+-----------------------------------------------------------------------------*/
+    xmlrpc_value * signatureListP;
+
+    signatureListP = xmlrpc_array_new(envP);
+    if (!envP->fault_occurred) {
+        if (sigListString == NULL || xmlrpc_streq(sigListString, "?")) {
+            /* No signatures -- leave the array empty */
+        } else {
+            const char * cursorP;
+            
+            cursorP = &sigListString[0];
+            
+            while (!envP->fault_occurred && *cursorP != '\0') {
+                xmlrpc_value * signatureP;
+                
+                parseOneSignature(envP, cursorP, &signatureP, &cursorP);
+                
+                /* cursorP now points at next signature in the list or the
+                   terminating NUL.
+                */
+                
+                if (!envP->fault_occurred) {
+                    xmlrpc_array_append_item(envP, signatureListP, signatureP);
+                    xmlrpc_DECREF(signatureP);
+                }
+            }
+            if (!envP->fault_occurred) {
+                unsigned int const arraySize = 
+                    xmlrpc_array_size(envP, signatureListP);
+                XMLRPC_ASSERT_ENV_OK(envP);
+                if (arraySize < 1)
+                    xmlrpc_faultf(envP, "Signature string is empty.");
+            }
+        }
+        if (envP->fault_occurred)
+            xmlrpc_DECREF(signatureListP);
+    }
+    *resultPP = signatureListP;
+}
+
+
+
+/*=========================================================================
+  system.multicall
+=========================================================================*/
+
+static xmlrpc_value *
+call_one_method(xmlrpc_env *env, xmlrpc_registry *registry,
+                xmlrpc_value *method_info) {
+
+    xmlrpc_value *result_val, *result;
+    char *method_name;
+    xmlrpc_value *param_array;
+
+    /* Error-handling preconditions. */
+    result = result_val = NULL;
+    
+    /* Extract our method name and parameters. */
+    xmlrpc_parse_value(env, method_info, "{s:s,s:A,*}",
+                       "methodName", &method_name,
+                       "params", &param_array);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Watch out for a deep recursion attack. */
+    if (strcmp(method_name, "system.multicall") == 0)
+        XMLRPC_FAIL(env, XMLRPC_REQUEST_REFUSED_ERROR,
+                    "Recursive system.multicall strictly forbidden");
+    
+    /* Perform the call. */
+    xmlrpc_dispatchCall(env, registry, method_name, param_array, &result_val);
+    XMLRPC_FAIL_IF_FAULT(env);
+    
+    /* Build our one-item result array. */
+    result = xmlrpc_build_value(env, "(V)", result_val);
+    XMLRPC_FAIL_IF_FAULT(env);
+    
+ cleanup:
+    if (result_val)
+        xmlrpc_DECREF(result_val);
+    if (env->fault_occurred) {
+        if (result)
+            xmlrpc_DECREF(result);
+        return NULL;
+    }
+    return result;
+}
+
+
+
+static xmlrpc_value *
+system_multicall(xmlrpc_env *env,
+                 xmlrpc_value *param_array,
+                 void *user_data) {
+
+    xmlrpc_registry *registry;
+    xmlrpc_value *methlist, *methinfo, *results, *result;
+    size_t size, i;
+    xmlrpc_env env2;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_VALUE_OK(param_array);
+    XMLRPC_ASSERT_PTR_OK(user_data);
+
+    /* Error-handling preconditions. */
+    results = result = NULL;
+    xmlrpc_env_init(&env2);
+    
+    /* Turn our arguments into something more useful. */
+    registry = (xmlrpc_registry*) user_data;
+    xmlrpc_parse_value(env, param_array, "(A)", &methlist);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Create an empty result list. */
+    results = xmlrpc_build_value(env, "()");
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Loop over our input list, calling each method in turn. */
+    size = xmlrpc_array_size(env, methlist);
+    XMLRPC_ASSERT_ENV_OK(env);
+    for (i = 0; i < size; i++) {
+        methinfo = xmlrpc_array_get_item(env, methlist, i);
+        XMLRPC_ASSERT_ENV_OK(env);
+        
+        /* Call our method. */
+        xmlrpc_env_clean(&env2);
+        xmlrpc_env_init(&env2);
+        result = call_one_method(&env2, registry, methinfo);
+        
+        /* Turn any fault into a structure. */
+        if (env2.fault_occurred) {
+            XMLRPC_ASSERT(result == NULL);
+            result = 
+                xmlrpc_build_value(env, "{s:i,s:s}",
+                                   "faultCode", (xmlrpc_int32) env2.fault_code,
+                                   "faultString", env2.fault_string);
+            XMLRPC_FAIL_IF_FAULT(env);
+        }
+        
+        /* Append this method result to our master array. */
+        xmlrpc_array_append_item(env, results, result);
+        xmlrpc_DECREF(result);
+        result = NULL;
+        XMLRPC_FAIL_IF_FAULT(env);
+    }
+
+ cleanup:
+    xmlrpc_env_clean(&env2);
+    if (result)
+        xmlrpc_DECREF(result);
+    if (env->fault_occurred) {
+        if (results)
+            xmlrpc_DECREF(results);
+        return NULL;
+    }
+    return results;
+}
+
+
+
+static struct systemMethodReg const multicall = {
+    "system.multicall",
+    &system_multicall,
+    "A:A",
+    "Process an array of calls, and return an array of results.  Calls should "
+    "be structs of the form {'methodName': string, 'params': array}. Each "
+    "result will either be a single-item array containg the result value, or "
+    "a struct of the form {'faultCode': int, 'faultString': string}.  This "
+    "is useful when you need to make lots of small calls without lots of "
+    "round trips.",
+};
+
+
+/*=========================================================================
+   system.listMethods
+=========================================================================*/
+
+
+
+static xmlrpc_value *
+system_listMethods(xmlrpc_env *env,
+                   xmlrpc_value *param_array,
+                   void *user_data) {
+
+    xmlrpc_registry *registry;
+    xmlrpc_value *method_names, *method_name, *method_info;
+    size_t size, i;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_VALUE_OK(param_array);
+    XMLRPC_ASSERT_PTR_OK(user_data);
+
+    /* Error-handling preconditions. */
+    method_names = NULL;
+
+    /* Turn our arguments into something more useful. */
+    registry = (xmlrpc_registry*) user_data;
+    xmlrpc_parse_value(env, param_array, "()");
+    XMLRPC_FAIL_IF_FAULT(env);
+    
+    /* Make sure we're allowed to introspect. */
+    if (!registry->_introspection_enabled)
+        XMLRPC_FAIL(env, XMLRPC_INTROSPECTION_DISABLED_ERROR,
+                    "Introspection disabled for security reasons");
+    
+    /* Iterate over all the methods in the registry, adding their names
+    ** to a list. */
+    method_names = xmlrpc_build_value(env, "()");
+    XMLRPC_FAIL_IF_FAULT(env);
+    size = xmlrpc_struct_size(env, registry->_methods);
+    XMLRPC_FAIL_IF_FAULT(env);
+    for (i = 0; i < size; i++) {
+        xmlrpc_struct_get_key_and_value(env, registry->_methods, i,
+                                        &method_name, &method_info);
+        XMLRPC_FAIL_IF_FAULT(env);
+        xmlrpc_array_append_item(env, method_names, method_name);
+        XMLRPC_FAIL_IF_FAULT(env);
+    }
+
+ cleanup:
+    if (env->fault_occurred) {
+        if (method_names)
+            xmlrpc_DECREF(method_names);
+        return NULL;
+    }
+    return method_names;
+}
+
+static struct systemMethodReg const listMethods = {
+    "system.listMethods",
+    &system_listMethods,
+    "A:",
+    "Return an array of all available XML-RPC methods on this server.",
+};
+
+
+
+/*=========================================================================
+  system.methodHelp
+=========================================================================*/
+
+static xmlrpc_value *
+system_methodHelp(xmlrpc_env *env,
+                  xmlrpc_value *param_array,
+                  void *user_data) {
+
+    xmlrpc_registry *registry;
+    char *method_name;
+    xmlrpc_value *ignored1, *ignored2, *ignored3, *help;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_VALUE_OK(param_array);
+    XMLRPC_ASSERT_PTR_OK(user_data);
+
+    /* Turn our arguments into something more useful. */
+    registry = (xmlrpc_registry*) user_data;
+    xmlrpc_parse_value(env, param_array, "(s)", &method_name);
+    XMLRPC_FAIL_IF_FAULT(env);
+    
+    /* Make sure we're allowed to introspect. */
+    if (!registry->_introspection_enabled)
+        XMLRPC_FAIL(env, XMLRPC_INTROSPECTION_DISABLED_ERROR,
+                    "Introspection disabled for security reasons");
+    
+    /* Get our documentation string. */
+    xmlrpc_parse_value(env, registry->_methods, "{s:(VVVV*),*}",
+                       method_name, &ignored1, &ignored2, &ignored3, &help);
+    XMLRPC_FAIL_IF_FAULT(env);
+    
+ cleanup:
+    if (env->fault_occurred)
+        return NULL;
+    xmlrpc_INCREF(help);
+    return help;
+}
+
+
+static struct systemMethodReg const methodHelp = {
+    "system.methodHelp",
+    &system_methodHelp,
+    "s:s",
+    "Given the name of a method, return a help string.",
+};
+
+
+
+static void
+getMethodInfo(xmlrpc_env *      const envP,
+              xmlrpc_registry * const registryP,
+              const char *      const methodName,
+              xmlrpc_value **   const methodInfoPP) {
+/*----------------------------------------------------------------------------
+   Look up the method info for the named method.  Method info
+   is an array (ppss):
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+    xmlrpc_value * methodInfoP;
+    
+    xmlrpc_env_init(&env);
+    
+    /* We can't use xmlrpc_struct_find_value() here because it isn't
+       thread-safe (it manipulates the reference count) and servers
+       sometimes call system methods from multiple threads at once.
+    */
+    methodInfoP = xmlrpc_struct_get_value(
+        &env, registryP->_methods, methodName);
+    
+    if (env.fault_occurred) {
+        if (env.fault_code == XMLRPC_INDEX_ERROR)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_NO_SUCH_METHOD_ERROR,
+                "Method '%s' does not exist", methodName);
+        else
+            xmlrpc_faultf(envP, "Unable to look up method named '%s' in the "
+                          "registry.  %s", methodName, env.fault_string);
+    } else
+        *methodInfoPP = methodInfoP;
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+/*=========================================================================
+  system.methodSignature
+==========================================================================*/
+
+static void
+buildNoSigSuppliedResult(xmlrpc_env *    const envP,
+                         xmlrpc_value ** const resultPP) {
+
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    *resultPP = xmlrpc_string_new(&env, "undef");
+    if (env.fault_occurred)
+        xmlrpc_faultf(envP, "Unable to construct 'undef'.  %s",
+                      env.fault_string);
+
+    xmlrpc_env_clean(&env);
+}
+    
+
+
+static void
+makeSigListCopy(xmlrpc_env *    const envP,
+                xmlrpc_value *  const oldP,
+                xmlrpc_value ** const newPP) {
+
+    xmlrpc_value * newP;
+
+    newP = xmlrpc_array_new(envP);
+
+    if (!envP->fault_occurred) {
+        unsigned int const size = xmlrpc_array_size(envP, oldP);
+        if (!envP->fault_occurred) {
+            unsigned int i;
+            for (i = 0; i < size; ++i) {
+                /* We can't use xmlrpc_array_read_item() here because
+                   it isn't thread-safe (it manipulates the reference count)
+                   an servers sometimes call system methods from multiple
+                   threads at once.
+                */
+                xmlrpc_value * const itemP =
+                    xmlrpc_array_get_item(envP, oldP, i);
+                xmlrpc_array_append_item(envP, newP, itemP);
+            }
+        }                
+    }
+    *newPP = newP;
+}
+
+
+
+static void
+getSignatureList(xmlrpc_env *      const envP,
+                 xmlrpc_registry * const registryP,
+                 const char *      const methodName,
+                 xmlrpc_value **   const signatureListPP) {
+/*----------------------------------------------------------------------------
+  Get the signature list array for method named 'methodName' from registry
+  'registryP'.
+
+  If there is no signature information for the method in the registry,
+  return *signatureListPP == NULL.
+
+  Nonexistent method is considered a failure.
+-----------------------------------------------------------------------------*/
+    xmlrpc_value * methodInfoP;
+
+    getMethodInfo(envP, registryP, methodName, &methodInfoP);
+    if (!envP->fault_occurred) {
+        xmlrpc_env env;
+        xmlrpc_value * signatureListP;
+        
+        xmlrpc_env_init(&env);
+        
+        /* We can't use xmlrpc_array_read_item() because it isn't thread
+           safe (it manipulates the reference count) and servers sometimes
+           run system methods from multiple threads at once.
+        */
+        signatureListP = xmlrpc_array_get_item(&env, methodInfoP, 2);
+
+        if (env.fault_occurred)
+            xmlrpc_faultf(envP, "Failed to read signature list "
+                          "from method info array.  %s",
+                          env.fault_string);
+        else {
+            int arraySize;
+
+            arraySize = xmlrpc_array_size(&env, signatureListP);
+            if (env.fault_occurred)
+                xmlrpc_faultf(envP, "xmlrpc_array_size() on signature "
+                              "list array failed!  %s", env.fault_string);
+            else {
+                if (arraySize == 0)
+                    *signatureListPP = NULL;
+                else {
+                    makeSigListCopy(envP, signatureListP, signatureListPP);
+                }
+            }
+        }
+        xmlrpc_env_clean(&env);
+    }
+}
+
+
+
+static xmlrpc_value *
+system_methodSignature(xmlrpc_env *   const envP,
+                       xmlrpc_value * const paramArrayP,
+                       void *         const userData) {
+
+    xmlrpc_registry * const registryP = (xmlrpc_registry *) userData;
+
+    xmlrpc_value * retvalP;
+    const char * methodName;
+    xmlrpc_env env;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+    XMLRPC_ASSERT_PTR_OK(userData);
+
+    xmlrpc_env_init(&env);
+
+    /* Turn our arguments into something more useful. */
+    xmlrpc_decompose_value(&env, paramArrayP, "(s)", &methodName);
+    if (env.fault_occurred)
+        xmlrpc_env_set_fault_formatted(
+            envP, env.fault_code,
+            "Invalid parameter list.  %s", env.fault_string);
+    else {
+        if (!registryP->_introspection_enabled)
+            xmlrpc_env_set_fault(envP, XMLRPC_INTROSPECTION_DISABLED_ERROR,
+                                 "Introspection disabled on this server");
+        else {
+            xmlrpc_value * signatureListP;
+
+            getSignatureList(envP, registryP, methodName, &signatureListP);
+
+            if (!envP->fault_occurred) {
+                if (signatureListP)
+                    retvalP = signatureListP;
+                else
+                    buildNoSigSuppliedResult(envP, &retvalP);
+            }
+        }
+        xmlrpc_strfree(methodName);
+    }
+    xmlrpc_env_clean(&env);
+
+    return retvalP;
+}
+
+
+
+static struct systemMethodReg const methodSignature = {
+    "system.methodSignature",
+    &system_methodSignature,
+    "A:s",
+    "Given the name of a method, return an array of legal signatures. "
+    "Each signature is an array of strings.  The first item of each signature "
+    "is the return type, and any others items are parameter types.",
+};
+
+
+
+
+/*=========================================================================
+  system.shutdown
+==========================================================================*/
+
+static xmlrpc_value *
+system_shutdown(xmlrpc_env *   const envP,
+                xmlrpc_value * const paramArrayP,
+                void *         const userData) {
+    
+    xmlrpc_registry * const registryP = (xmlrpc_registry *) userData;
+
+    xmlrpc_value * retvalP;
+    const char * comment;
+    xmlrpc_env env;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+    XMLRPC_ASSERT_PTR_OK(userData);
+
+    xmlrpc_env_init(&env);
+
+    retvalP = NULL;  /* quiet compiler warning */
+
+    /* Turn our arguments into something more useful. */
+    xmlrpc_decompose_value(&env, paramArrayP, "(s)", &comment);
+    if (env.fault_occurred)
+        xmlrpc_env_set_fault_formatted(
+            envP, env.fault_code,
+            "Invalid parameter list.  %s", env.fault_string);
+    else {
+        if (!registryP->_shutdown_server_fn)
+            xmlrpc_env_set_fault(
+                envP, 0, "This server program is not capable of "
+                "shutting down");
+        else {
+            registryP->_shutdown_server_fn(
+                &env, registryP->_shutdown_context, comment);
+
+            if (env.fault_occurred)
+                xmlrpc_env_set_fault(envP, env.fault_code, env.fault_string);
+            else {
+                retvalP = xmlrpc_int_new(&env, 0);
+                
+                if (env.fault_occurred)
+                    xmlrpc_faultf(envP,
+                                  "Failed to construct return value.  %s",
+                                  env.fault_string);
+            }
+        }
+        xmlrpc_strfree(comment);
+    }
+    xmlrpc_env_clean(&env);
+
+    return retvalP;
+}
+
+
+
+static struct systemMethodReg const shutdown = {
+    "system.shutdown",
+    &system_shutdown,
+    "i:s",
+    "Shut down the server.  Return code is always zero.",
+};
+
+
+
+/*============================================================================
+  Installer of system methods
+============================================================================*/
+
+static void
+registerSystemMethod(xmlrpc_env *           const envP,
+                     xmlrpc_registry *      const registryP,
+                     struct systemMethodReg const methodReg) {
+
+    xmlrpc_env env;
+    xmlrpc_env_init(&env);
+    
+    xmlrpc_registry_add_method_w_doc(
+        &env, registryP, NULL, methodReg.methodName,
+        methodReg.methodFunction, registryP,
+        methodReg.signatureString, methodReg.helpText);
+    
+    if (env.fault_occurred)
+        xmlrpc_faultf(envP, "Failed to register '%s' system method.  %s",
+                      methodReg.methodName, env.fault_string);
+    
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_installSystemMethods(xmlrpc_env *      const envP,
+                            xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+   Install the built-in methods (system.*) into registry 'registryP'.
+-----------------------------------------------------------------------------*/
+    if (!envP->fault_occurred)
+        registerSystemMethod(envP, registryP, listMethods);
+
+    if (!envP->fault_occurred) 
+        registerSystemMethod(envP, registryP, methodSignature);
+
+    if (!envP->fault_occurred)
+        registerSystemMethod(envP, registryP, methodHelp);
+
+    if (!envP->fault_occurred)
+        registerSystemMethod(envP, registryP, multicall);
+
+    if (!envP->fault_occurred)
+        registerSystemMethod(envP, registryP, shutdown);
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2001 by Eric Kidd. All rights reserved.
+** Copyright (C) 2001 by Luke Howard. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
diff --git a/src/system_method.h b/src/system_method.h
new file mode 100644 (file)
index 0000000..f9dff5f
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef SYSTEM_METHOD_H_INCLUDED
+#define SYSTEM_METHOD_H_INCLUDED
+
+
+void
+xmlrpc_installSystemMethods(struct _xmlrpc_env *      const envP,
+                            struct _xmlrpc_registry * const registryP);
+
+void
+xmlrpc_buildSignatureArray(xmlrpc_env *    const envP,
+                           const char *    const sigListString,
+                           xmlrpc_value ** const resultPP);
+
+#endif
diff --git a/src/test/.cvsignore b/src/test/.cvsignore
new file mode 100644 (file)
index 0000000..41bf38d
--- /dev/null
@@ -0,0 +1,2 @@
+test
+cgitest1
diff --git a/src/test/Makefile b/src/test/Makefile
new file mode 100644 (file)
index 0000000..feefa7b
--- /dev/null
@@ -0,0 +1,93 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+SUBDIR = src/test
+BUILDDIR = $(SRCDIR)
+VPATH = .:$(SRCDIR)
+
+include $(BUILDDIR)/Makefile.config
+
+XMLRPC_C_CONFIG = $(BUILDDIR)/xmlrpc-c-config.test
+
+LDADD_CLIENT = \
+  $(shell $(XMLRPC_C_CONFIG) client --ldadd)
+LDADD_ABYSS_SERVER = \
+  $(shell $(XMLRPC_C_CONFIG) abyss-server --ldadd)
+LDADD_CGI_SERVER = \
+  $(shell $(XMLRPC_C_CONFIG) cgi-server --ldadd)
+
+default: all
+
+INCLUDES = -I$(BUILDDIR) -I$(SRCDIR) \
+           -I $(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
+
+PROGS = test cgitest1
+
+all: $(PROGS)
+
+LDFLAGS = $(LADD)
+
+TEST_OBJS = \
+  test.o \
+  cgi.o \
+  method_registry.o \
+  parse_xml.o \
+  serialize.o \
+  server_abyss.o \
+  value.o \
+  xml_data.o \
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  TEST_OBJS += client.o
+  LIBXMLRPC_CLIENT_DEP = $(LIBXMLRPC_CLIENT)
+else
+  TEST_OBJS += client_dummy.o
+  LIBXMLRPC_CLIENT_DEP =
+endif
+
+include $(SRCDIR)/Makefile.common
+
+test: $(TEST_OBJS) $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) \
+  $(LIBXMLRPC_SERVER_A) $(LIBXMLRPC_SERVER_ABYSS_A) $(LIBXMLRPC_XML) \
+   $(LIBXMLRPC_CLIENT_DEP) $(LIBXMLRPC_ABYSS_A) $(CASPRINTF)
+       $(CCLD) -o $@ $(LDFLAGS) \
+           $(TEST_OBJS) $(LDADD_CLIENT) $(LDADD_ABYSS_SERVER) $(CASPRINTF)
+
+cgitest1:%:%.o $(LIBXMLRPC_SERVER_A) $(LIBXMLRPC_SERVER_CGI_A) \
+  $(LIBXMLRPC_A) $(LIBXMLRPC_UTIL_A) $(LIBXMLRPC_XML)
+       $(CCLD) -o $@ $< $(LDFLAGS) $(LDADD_CGI_SERVER)
+
+CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+OBJS = $(TEST_OBJS) cgitest1.o
+
+$(OBJS):%.o:%.c
+       $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+# Note the difference between 'check' and 'runtests'.  'check' means to check
+# our own correctness.  'runtests' means to run the tests that check our
+# parent's correctness
+
+.PHONY: check
+check:
+
+.PHONY: runtests
+runtests: test cgitest1
+       ./test
+
+.PHONY: install
+install:
+
+.PHONY: clean clean-local distclean
+clean: clean-common clean-local
+clean-local:
+       rm -f $(PROGS)
+
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
+
+include Makefile.depend
+
+
diff --git a/src/test/Makefile.depend b/src/test/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/test/cgi.c b/src/test/cgi.c
new file mode 100644 (file)
index 0000000..52c0c08
--- /dev/null
@@ -0,0 +1,60 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "xmlrpc_config.h"
+
+#include "test.h"
+#include "cgi.h"
+
+static const char cgiResponse1[] =
+  "....Status: 200 OK\n"
+  "Content-type: text/xml; charset=\"utf-8\"\n"
+  "Content-length: 141\n"
+  "\n"
+  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+  "<methodResponse>\r\n"
+  "<params>\r\n"
+  "<param><value><i4>12</i4></value></param>\r\n"
+  "</params>\r\n"
+  "</methodResponse>\r\n";
+
+
+#define TESTDATA_DIR "data"
+#define DIRSEP DIRECTORY_SEPARATOR
+
+void
+test_server_cgi(void) {
+/*----------------------------------------------------------------------------
+  Here, we pretend to be a web server when someone has requested a POST
+  to the CGI script "cgitest1".
+-----------------------------------------------------------------------------*/
+    FILE * cgiOutputP;
+
+    printf("Running CGI tests...\n");
+
+    cgiOutputP = popen("REQUEST_METHOD=POST "
+                       "CONTENT_TYPE=text/xml "
+                       "CONTENT_LENGTH=211 "
+                       "./cgitest1 "
+                       "<"
+                       TESTDATA_DIR DIRSEP "sample_add_call.xml",
+                       "r");
+
+    if (cgiOutputP == NULL)
+        TEST_ERROR("Unable to run 'cgitest' program.");
+    else {
+        unsigned char cgiResponse[4096];
+        size_t bytesRead;
+
+        bytesRead = fread(cgiResponse, 1, sizeof(cgiResponse), cgiOutputP);
+
+        TEST(bytesRead == strlen(cgiResponse1));
+
+        TEST(memcmp(cgiResponse, cgiResponse1, bytesRead) == 0);
+    }
+    fclose(cgiOutputP);
+    printf("\n");
+    printf("CGI tests done.\n");
+}
diff --git a/src/test/cgi.h b/src/test/cgi.h
new file mode 100644 (file)
index 0000000..4e2de99
--- /dev/null
@@ -0,0 +1,2 @@
+void
+test_server_cgi(void);
diff --git a/src/test/cgitest1.c b/src/test/cgitest1.c
new file mode 100644 (file)
index 0000000..7ce6909
--- /dev/null
@@ -0,0 +1,79 @@
+/*============================================================================
+  Act like a CGI script -- read POST data from Standard Input, interpret
+  it as an XML-RPC call, and write an XML-RPC response to Standard Output.
+
+  This is for use by a test program.
+============================================================================*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "xmlrpc-c/server_cgi.h"
+
+#include "test.h"
+
+
+int total_tests;
+int total_failures;
+
+
+
+static xmlrpc_value *
+sample_add(xmlrpc_env *   const env, 
+           xmlrpc_value * const param_array, 
+           void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_int32 x, y, z;
+
+    /* Parse our argument array. */
+    xmlrpc_decompose_value(env, param_array, "(ii)", &x, &y);
+    if (env->fault_occurred)
+        return NULL;
+
+    /* Add our two numbers. */
+    z = x + y;
+
+    /* Return our result. */
+    return xmlrpc_build_value(env, "i", z);
+}
+
+
+
+int
+main(int     argc ATTR_UNUSED,
+     char ** argv ATTR_UNUSED) {
+
+    xmlrpc_env env;
+    xmlrpc_registry * registryP;
+    xmlrpc_value * argArrayP;
+
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+    TEST(registryP != NULL);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_registry_add_method(&env, registryP, NULL, "sample.add",
+                               sample_add, NULL);
+    TEST_NO_FAULT(&env);
+
+    argArrayP = xmlrpc_build_value(&env, "(ii)",
+                                   (xmlrpc_int32) 25, (xmlrpc_int32) 17); 
+    TEST_NO_FAULT(&env);
+
+    /* The following reads from Standard Input and writes to Standard
+       Output
+    */
+    xmlrpc_server_cgi_process_call(registryP);
+
+    xmlrpc_DECREF(argArrayP);
+    xmlrpc_registry_free(registryP);
+
+    return 0;
+}
diff --git a/src/test/client.c b/src/test/client.c
new file mode 100644 (file)
index 0000000..3a0c6f7
--- /dev/null
@@ -0,0 +1,255 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+
+#include "test.h"
+#include "client.h"
+
+
+static void
+testGlobalConst(void) {
+
+    xmlrpc_env env;
+    xmlrpc_env_init(&env);
+
+    xmlrpc_client_setup_global_const(&env);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_client_teardown_global_const();
+
+    xmlrpc_client_setup_global_const(&env);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_setup_global_const(&env);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_client_teardown_global_const();
+    xmlrpc_client_teardown_global_const();
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testCreateDestroy(void) {
+
+    xmlrpc_env env;
+    xmlrpc_client * clientP;
+    struct xmlrpc_clientparms clientParms1;
+    struct xmlrpc_curl_xportparms curlTransportParms1;
+
+    xmlrpc_env_init(&env);
+
+    xmlrpc_client_create(&env, 0, "testprog", "1.0", NULL, 0, &clientP);
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+        /* Didn't set up global const */
+
+    xmlrpc_client_setup_global_const(&env);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_client_create(&env, 0, "testprog", "1.0", NULL, 0, &clientP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_destroy(clientP);
+
+    xmlrpc_client_create(&env, 0, "testprog", "1.0", &clientParms1, 0,
+                         &clientP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_destroy(clientP);
+
+    clientParms1.transport = "curl";
+    xmlrpc_client_create(&env, 0, "testprog", "1.0",
+                        &clientParms1, XMLRPC_CPSIZE(transport), &clientP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_destroy(clientP);
+
+    clientParms1.transportparmsP = NULL;
+    xmlrpc_client_create(&env, 0, "testprog", "1.0",
+                         &clientParms1, XMLRPC_CPSIZE(transportparmsP),
+                         &clientP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_destroy(clientP);
+
+    clientParms1.transportparmsP = (struct xmlrpc_xportparms *)(void *)
+        &curlTransportParms1;
+
+    xmlrpc_client_create(&env, 0, "testprog", "1.0",
+                         &clientParms1, XMLRPC_CPSIZE(transportparmsP),
+                         &clientP);
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+    clientParms1.transportparm_size = 0;
+    xmlrpc_client_create(&env, 0, "testprog", "1.0",
+                         &clientParms1, XMLRPC_CPSIZE(transportparm_size),
+                         &clientP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_destroy(clientP);
+
+    curlTransportParms1.network_interface = "eth0";
+    clientParms1.transportparm_size = XMLRPC_CXPSIZE(network_interface);
+    xmlrpc_client_create(&env, 0, "testprog", "1.0",
+                         &clientParms1, XMLRPC_CPSIZE(transportparm_size),
+                         &clientP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_destroy(clientP);
+
+    curlTransportParms1.no_ssl_verifypeer = 1;
+    curlTransportParms1.no_ssl_verifyhost = 1;
+    clientParms1.transportparm_size = XMLRPC_CXPSIZE(no_ssl_verifyhost);
+    xmlrpc_client_create(&env, 0, "testprog", "1.0",
+                         &clientParms1, XMLRPC_CPSIZE(transportparm_size),
+                         &clientP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_destroy(clientP);
+
+    curlTransportParms1.user_agent = "testprog/1.0";
+    clientParms1.transportparm_size = XMLRPC_CXPSIZE(user_agent);
+    xmlrpc_client_create(&env, 0, "testprog", "1.0",
+                         &clientParms1, XMLRPC_CPSIZE(transportparm_size),
+                         &clientP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_destroy(clientP);
+
+    xmlrpc_client_teardown_global_const();
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testSynchCall(void) {
+
+    xmlrpc_env env;
+    xmlrpc_client * clientP;
+    xmlrpc_value * resultP;
+    xmlrpc_value * emptyArrayP;
+    xmlrpc_server_info * noSuchServerInfoP;
+
+    xmlrpc_env_init(&env);
+
+    emptyArrayP = xmlrpc_array_new(&env);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_client_setup_global_const(&env);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_client_create(&env, 0, "testprog", "1.0", NULL, 0, &clientP);
+    TEST_NO_FAULT(&env);
+
+    noSuchServerInfoP = xmlrpc_server_info_new(&env, "nosuchserver");
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_client_call2(&env, clientP, noSuchServerInfoP, "nosuchmethod",
+                        emptyArrayP, &resultP);
+    TEST_FAULT(&env, XMLRPC_NETWORK_ERROR);  /* No such server */
+
+    xmlrpc_client_call2f(&env, clientP, "nosuchserver", "nosuchmethod",
+                          &resultP, "(i)", 7);
+    TEST_FAULT(&env, XMLRPC_NETWORK_ERROR);  /* No such server */
+
+    xmlrpc_server_info_free(noSuchServerInfoP);
+
+    xmlrpc_client_destroy(clientP);
+
+    xmlrpc_DECREF(emptyArrayP);
+    
+    xmlrpc_client_teardown_global_const();
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testInitCleanup(void) {
+
+    xmlrpc_env env;
+    struct xmlrpc_clientparms clientParms1;
+    struct xmlrpc_curl_xportparms curlTransportParms1;
+
+    xmlrpc_env_init(&env);
+
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0", NULL, 0);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0", &clientParms1, 0);
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    clientParms1.transport = "curl";
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0",
+                        &clientParms1, XMLRPC_CPSIZE(transport));
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    clientParms1.transportparmsP = NULL;
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0",
+                        &clientParms1, XMLRPC_CPSIZE(transportparmsP));
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    clientParms1.transportparmsP = (struct xmlrpc_xportparms *)(void *)
+        &curlTransportParms1;
+
+    /* Fails because we didn't include transportparm_size: */
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0",
+                        &clientParms1, XMLRPC_CPSIZE(transportparmsP));
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+    clientParms1.transportparm_size = 0;
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0",
+                        &clientParms1, XMLRPC_CPSIZE(transportparm_size));
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    curlTransportParms1.network_interface = "eth0";
+    clientParms1.transportparm_size = XMLRPC_CXPSIZE(network_interface);
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0",
+                        &clientParms1, XMLRPC_CPSIZE(transportparm_size));
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    curlTransportParms1.no_ssl_verifypeer = 1;
+    curlTransportParms1.no_ssl_verifyhost = 1;
+    clientParms1.transportparm_size = XMLRPC_CXPSIZE(no_ssl_verifyhost);
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0",
+                        &clientParms1, XMLRPC_CPSIZE(transportparm_size));
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    curlTransportParms1.user_agent = "testprog/1.0";
+    clientParms1.transportparm_size = XMLRPC_CXPSIZE(user_agent);
+    xmlrpc_client_init2(&env, 0, "testprog", "1.0",
+                        &clientParms1, XMLRPC_CPSIZE(transportparm_size));
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    xmlrpc_client_init(0, "testprog", "1.0");
+    TEST_NO_FAULT(&env);
+    xmlrpc_client_cleanup();
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void 
+test_client(void) {
+
+    printf("Running client tests.");
+
+    testGlobalConst();
+    testCreateDestroy();
+    testInitCleanup();
+    testSynchCall();
+
+    printf("\n");
+    printf("Client tests done.\n");
+}
diff --git a/src/test/client.h b/src/test/client.h
new file mode 100644 (file)
index 0000000..2727617
--- /dev/null
@@ -0,0 +1,2 @@
+void 
+test_client(void);
diff --git a/src/test/client_dummy.c b/src/test/client_dummy.c
new file mode 100644 (file)
index 0000000..6377fb8
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+#include "client.h"
+
+
+
+void 
+test_client(void) {
+
+    printf("Running dummy client test.");
+
+    printf("\n");
+    printf("Client tests done.\n");
+}
diff --git a/src/test/data/req_no_params.xml b/src/test/data/req_no_params.xml
new file mode 100644 (file)
index 0000000..6ed51a4
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This may or may not be legal XML-RPC, but some old clients (including
+Ruby and xmlrpc-epi) send it.  This should be interpreted as a call with no
+parameters. -->
+
+<methodCall>
+  <methodName>foo</methodName>
+</methodCall>
diff --git a/src/test/data/req_out_of_order.xml b/src/test/data/req_out_of_order.xml
new file mode 100644 (file)
index 0000000..8b078a4
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<methodCall>
+  <params>
+    <param>
+      <value><int>2</int></value>
+    </param>
+    <param>
+      <value><int>2</int></value>
+    </param>
+  </params>
+  <methodName>add</methodName>
+</methodCall>
diff --git a/src/test/data/req_value_name.xml b/src/test/data/req_value_name.xml
new file mode 100644 (file)
index 0000000..b55d4f0
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<methodCall>
+  <methodName>foo</methodName>
+  <params>
+    <param>
+      <value><struct>
+        <member>
+          <value><i4>0</i4></value>
+          <name>child elements reversed!</name>
+        </member>
+      </struct></value>
+    </param>
+  </params>
+</methodCall>
diff --git a/src/test/data/sample_add_call.xml b/src/test/data/sample_add_call.xml
new file mode 100644 (file)
index 0000000..b11336a
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<methodCall>\r
+<methodName>sample.add</methodName>\r
+<params>\r
+<param><value><i4>5</i4></value></param>\r
+<param><value><i4>7</i4></value></param>\r
+</params>\r
+</methodCall>\r
diff --git a/src/test/eftest_wrapper.sh b/src/test/eftest_wrapper.sh
new file mode 100644 (file)
index 0000000..31606b7
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+echo "*** Testing for heap block overruns..."
+efrpctest
+if ! test $?; then exit 1; fi
+echo "*** Testing for heap block underruns..."
+EF_PROTECT_BELOW=1 efrpctest
+if ! test $?; then exit 1; fi
+
+echo "*** Testing for access to freed heap blocks..."
+EF_PROTECT_FREE=1 efrpctest
+if ! test $?; then exit 1; fi
+
+echo "*** Testing for single-byte overruns..."
+EF_ALIGNMENT=0 efrpctest
+if ! test $?; then exit 1; fi
diff --git a/src/test/http-req-simple.txt b/src/test/http-req-simple.txt
new file mode 100644 (file)
index 0000000..00db6a0
--- /dev/null
@@ -0,0 +1,11 @@
+POST /cgi-bin/sample-cgi.cgi 1.0\r
+Host: localhost\r
+Content-Type: text/xml\r
+Content-Length: 141\r
+\r
+<?xml version="1.0" encoding="UTF-8"?>\r
+<methodCall>\r
+  <methodName>system.listMethods</methodName>\r
+  <params>\r
+  </params>\r
+</methodCall>\r
diff --git a/src/test/method_registry.c b/src/test/method_registry.c
new file mode 100644 (file)
index 0000000..b8954f3
--- /dev/null
@@ -0,0 +1,524 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "casprintf.h"
+#include "girstring.h"
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+
+#include "test.h"
+#include "xml_data.h"
+#include "method_registry.h"
+
+
+#define FOO_USER_DATA ((void*) 0xF00)
+#define BAR_USER_DATA ((void*) 0xBAF)
+
+
+
+static xmlrpc_value *
+test_foo(xmlrpc_env *   const envP,
+         xmlrpc_value * const paramArrayP,
+         void *         const userData) {
+
+    xmlrpc_int32 x, y;
+
+    TEST_NO_FAULT(envP);
+    TEST(paramArrayP != NULL);
+    TEST(userData == FOO_USER_DATA);
+
+    xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+    TEST_NO_FAULT(envP);
+    TEST(x == 25);
+    TEST(y == 17);
+
+    return xmlrpc_build_value(envP, "i", (xmlrpc_int32) x + y);
+}
+
+
+
+static xmlrpc_value *
+test_bar(xmlrpc_env *   const envP,
+         xmlrpc_value * const paramArrayP,
+         void *         const userData) {
+
+    xmlrpc_int32 x, y;
+
+    TEST_NO_FAULT(envP);
+    TEST(paramArrayP != NULL);
+    TEST(userData == BAR_USER_DATA);
+
+    xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+    TEST_NO_FAULT(envP);
+    TEST(x == 25);
+    TEST(y == 17);
+
+    xmlrpc_env_set_fault(envP, 123, "Test fault");
+
+    return NULL;
+}
+
+
+
+static xmlrpc_value *
+test_default(xmlrpc_env *   const envP,
+             const char *   const host ATTR_UNUSED,
+             const char *   const methodName ATTR_UNUSED,
+             xmlrpc_value * const paramArrayP,
+             void *         const userData) {
+
+    xmlrpc_int32 x, y;
+
+    TEST_NO_FAULT(envP);
+    TEST(paramArrayP != NULL);
+    TEST(userData == FOO_USER_DATA);
+
+    xmlrpc_decompose_value(envP, paramArrayP, "(ii)", &x, &y);
+    TEST_NO_FAULT(envP);
+    TEST(x == 25);
+    TEST(y == 17);
+
+    return xmlrpc_build_value(envP, "i", 2 * (x + y));
+}
+
+
+
+static void
+doRpc(xmlrpc_env *      const envP,
+      xmlrpc_registry * const registryP,
+      const char *      const methodName,
+      xmlrpc_value *    const argArrayP,
+      xmlrpc_value **   const resultPP) {
+/*----------------------------------------------------------------------------
+   Do what an XML-RPC server would do -- pass an XML call to the registry
+   and get XML back.
+
+   Actually to our caller, we look more like an Xmlrpc-c client.  We're
+   both the client and the server all bound together.
+-----------------------------------------------------------------------------*/
+    xmlrpc_mem_block * callP;
+    xmlrpc_mem_block * responseP;
+
+    /* Build a call, and tell the registry to handle it. */
+    callP = xmlrpc_mem_block_new(envP, 0);
+    TEST_NO_FAULT(envP);
+    xmlrpc_serialize_call(envP, callP, methodName, argArrayP);
+    TEST_NO_FAULT(envP);
+    responseP = xmlrpc_registry_process_call(envP, registryP, NULL,
+                                             xmlrpc_mem_block_contents(callP),
+                                             xmlrpc_mem_block_size(callP));
+    TEST_NO_FAULT(envP);
+    TEST(responseP != NULL);
+
+    /* Parse the response. */
+    *resultPP = xmlrpc_parse_response(envP,
+                                      xmlrpc_mem_block_contents(responseP),
+                                      xmlrpc_mem_block_size(responseP));
+
+    xmlrpc_mem_block_free(callP);
+    xmlrpc_mem_block_free(responseP);
+}
+
+
+
+static const char * const validSigString[] = {
+    "i:",
+    "s:d",
+    "i:bds86SA",
+    "i:,i:",
+    "i:dd,s:,A:A",
+    "i:,",
+    "b:i,",
+    "b:i,b:,",
+    NULL
+};
+
+static const char * const invalidSigString[] = {
+    "",
+    "i",
+    "q",
+    "i:q",
+    "i:ddq",
+    ",",
+    ",i:",
+    "i,",
+    "b:i,,b:i",
+    "ii:",
+    "ii:ii",
+    NULL
+};
+
+
+static void
+test_signature_method(xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+   Test system.methodSignature system method.
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+    xmlrpc_value * argArrayP;
+    xmlrpc_value * resultP;
+    const char * type0;
+    const char * type1;
+    const char * type2;
+    const char * type3;
+    const char * type4;
+    const char * type5;
+    const char * type6;
+    const char * type7;
+    const char * nosigstring;
+
+    xmlrpc_env_init(&env);
+
+    argArrayP = xmlrpc_build_value(&env, "(s)", "test.nosuchmethod");
+    doRpc(&env, registryP, "system.methodSignature", argArrayP, &resultP);
+    TEST_FAULT(&env, XMLRPC_NO_SUCH_METHOD_ERROR);
+    xmlrpc_DECREF(argArrayP);
+
+    argArrayP = xmlrpc_build_value(&env, "(s)", "test.nosig0");
+
+    doRpc(&env, registryP, "system.methodSignature", argArrayP, &resultP);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_read_string(&env, resultP, &nosigstring);
+    TEST_NO_FAULT(&env);
+    
+    TEST(streq(nosigstring, "undef"));
+    strfree(nosigstring);
+    xmlrpc_DECREF(resultP);
+    xmlrpc_DECREF(argArrayP);
+
+    argArrayP = xmlrpc_build_value(&env, "(s)", "test.validsig0");
+    doRpc(&env, registryP, "system.methodSignature", argArrayP, &resultP);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_decompose_value(&env, resultP, "((s))", &type0);
+    TEST_NO_FAULT(&env);
+    TEST(streq(type0, "int"));
+    strfree(type0);
+    xmlrpc_DECREF(resultP);
+    xmlrpc_DECREF(argArrayP);
+
+    argArrayP = xmlrpc_build_value(&env, "(s)", "test.validsig2");
+    doRpc(&env, registryP, "system.methodSignature", argArrayP, &resultP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_decompose_value(&env, resultP, "((ssssssss))",
+                           &type0, &type1, &type2, &type3,
+                           &type4, &type5, &type6, &type7);
+    TEST_NO_FAULT(&env);
+    TEST(streq(type0, "int"));
+    TEST(streq(type1, "boolean"));
+    TEST(streq(type2, "double"));
+    TEST(streq(type3, "string"));
+    TEST(streq(type4, "dateTime.iso8601"));
+    TEST(streq(type5, "base64"));
+    TEST(streq(type6, "struct"));
+    TEST(streq(type7, "array"));
+    strfree(type0); strfree(type1); strfree(type2); strfree(type3);
+    strfree(type4); strfree(type5); strfree(type6); strfree(type7);
+    xmlrpc_DECREF(resultP);
+    xmlrpc_DECREF(argArrayP);
+
+    argArrayP = xmlrpc_build_value(&env, "(s)", "test.validsig3");
+    doRpc(&env, registryP, "system.methodSignature", argArrayP, &resultP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_decompose_value(&env, resultP, "((s)(s))", &type0, &type1);
+
+    TEST_NO_FAULT(&env);
+    TEST(streq(type0, "int"));
+    TEST(streq(type1, "int"));
+    xmlrpc_DECREF(resultP);
+    xmlrpc_DECREF(argArrayP);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_signature(void) {
+
+    xmlrpc_env env;
+    xmlrpc_registry * registryP;
+    uint i;
+
+    xmlrpc_env_init(&env);
+
+    printf("  Running signature tests.");
+
+    registryP = xmlrpc_registry_new(&env);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_registry_add_method_w_doc(&env, registryP, NULL, "test.nosig0",
+                                     test_foo, FOO_USER_DATA,
+                                     NULL, NULL);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_registry_add_method_w_doc(&env, registryP, NULL, "test.nosig1",
+                                     test_foo, FOO_USER_DATA,
+                                     "?", NULL);
+    TEST_NO_FAULT(&env);
+
+    for (i = 0; validSigString[i]; ++i) {
+        const char * methodName;
+        casprintf(&methodName, "test.validsig%u", i);
+        xmlrpc_registry_add_method_w_doc(&env, registryP, NULL, methodName,
+                                         test_foo, FOO_USER_DATA,
+                                         validSigString[i], NULL);
+        TEST_NO_FAULT(&env);
+        strfree(methodName);
+    }
+
+    for (i = 0; invalidSigString[i]; ++i) {
+        const char * methodName;
+        casprintf(&methodName, "test.invalidsig%u", i);
+        xmlrpc_registry_add_method_w_doc(&env, registryP, NULL, methodName,
+                                         test_foo, FOO_USER_DATA,
+                                         invalidSigString[i], NULL);
+        TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+        strfree(methodName);
+    }
+
+    test_signature_method(registryP);
+
+    xmlrpc_registry_free(registryP);
+
+    xmlrpc_env_clean(&env);
+
+    printf("\n");
+}
+
+
+
+static void
+test_system_multicall(xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+   Test system.multicall
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+    xmlrpc_value * multiP;
+    xmlrpc_int32 foo1_result, foo2_result;
+    xmlrpc_int32 bar_code, nosuch_code, multi_code, bogus1_code, bogus2_code;
+    char *bar_string, *nosuch_string, *multi_string;
+    char *bogus1_string, *bogus2_string;
+    xmlrpc_value * valueP;
+    xmlrpc_value * argArrayP;
+
+    xmlrpc_env_init(&env);
+
+    printf("  Running multicall tests.");
+
+    /* Build an argument array for our calls. */
+    argArrayP = xmlrpc_build_value(&env, "(ii)",
+                                   (xmlrpc_int32) 25, (xmlrpc_int32) 17); 
+    TEST_NO_FAULT(&env);
+
+    multiP = xmlrpc_build_value(&env,
+                               "(({s:s,s:V}{s:s,s:V}{s:s,s:V}"
+                               "{s:s,s:()}s{}{s:s,s:V}))",
+                               "methodName", "test.foo",
+                               "params", argArrayP,
+                               "methodName", "test.bar",
+                               "params", argArrayP,
+                               "methodName", "test.nosuch",
+                               "params", argArrayP,
+                               "methodName", "system.multicall",
+                               "params",
+                               "bogus_entry",
+                               "methodName", "test.foo",
+                               "params", argArrayP);
+    TEST_NO_FAULT(&env);    
+    doRpc(&env, registryP, "system.multicall", multiP, &valueP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_decompose_value(&env, valueP,
+                           "((i){s:i,s:s,*}{s:i,s:s,*}"
+                           "{s:i,s:s,*}{s:i,s:s,*}{s:i,s:s,*}(i))",
+                           &foo1_result,
+                           "faultCode", &bar_code,
+                           "faultString", &bar_string,
+                           "faultCode", &nosuch_code,
+                           "faultString", &nosuch_string,
+                           "faultCode", &multi_code,
+                           "faultString", &multi_string,
+                           "faultCode", &bogus1_code,
+                           "faultString", &bogus1_string,
+                           "faultCode", &bogus2_code,
+                           "faultString", &bogus2_string,
+                           &foo2_result);
+    xmlrpc_DECREF(valueP);
+    TEST_NO_FAULT(&env);    
+    TEST(foo1_result == 42);
+    TEST(bar_code == 123);
+    TEST(strcmp(bar_string, "Test fault") == 0);
+    TEST(nosuch_code == XMLRPC_NO_SUCH_METHOD_ERROR);
+    TEST(multi_code == XMLRPC_REQUEST_REFUSED_ERROR);
+    TEST(foo2_result == 42);
+    xmlrpc_DECREF(multiP);
+    free(bar_string);
+    free(nosuch_string);
+    free(multi_string);
+    free(bogus1_string);
+    free(bogus2_string);
+    
+    xmlrpc_DECREF(argArrayP);
+
+    xmlrpc_env_clean(&env);
+
+    printf("\n");
+}
+
+
+
+static void
+testCall(xmlrpc_registry * const registryP) {
+
+    xmlrpc_env env;
+    xmlrpc_env env2;
+    xmlrpc_value * argArrayP;
+    xmlrpc_value * valueP;
+    xmlrpc_int32 i;
+
+    printf("  Running call tests.");
+
+    xmlrpc_env_init(&env);
+
+    /* Build an argument array for our calls. */
+    argArrayP = xmlrpc_build_value(&env, "(ii)",
+                                   (xmlrpc_int32) 25, (xmlrpc_int32) 17); 
+    TEST_NO_FAULT(&env);
+
+    /* Call test.foo and check the result. */
+    doRpc(&env, registryP, "test.foo", argArrayP, &valueP);
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+    xmlrpc_decompose_value(&env, valueP, "i", &i);
+    xmlrpc_DECREF(valueP);
+    TEST_NO_FAULT(&env);
+    TEST(i == 42);
+
+    /* Call test.bar and check the result. */
+    xmlrpc_env_init(&env2);
+    doRpc(&env2, registryP, "test.bar", argArrayP, &valueP);
+    TEST(env2.fault_occurred);
+    TEST(env2.fault_code == 123);
+    TEST(env2.fault_string && strcmp(env2.fault_string, "Test fault") == 0);
+    xmlrpc_env_clean(&env2);
+
+    /* Call a non-existant method and check the result. */
+    xmlrpc_env_init(&env2);
+    doRpc(&env2, registryP, "test.nosuch", argArrayP, &valueP);
+    TEST(valueP == NULL);
+    TEST_FAULT(&env2, XMLRPC_NO_SUCH_METHOD_ERROR);
+    xmlrpc_env_clean(&env2);
+
+    xmlrpc_DECREF(argArrayP);
+
+    xmlrpc_env_clean(&env);
+
+    printf("\n");
+}
+
+
+
+static void
+testDefaultMethod(xmlrpc_registry * const registryP) {
+    
+    xmlrpc_env env;
+    xmlrpc_value * argArrayP;
+    xmlrpc_value * valueP;
+    xmlrpc_int32 i;
+    xmlrpc_env_init(&env);
+
+    printf("  Running default method tests.");
+
+    /* Build an argument array for our calls. */
+    argArrayP = xmlrpc_build_value(&env, "(ii)",
+                                   (xmlrpc_int32) 25, (xmlrpc_int32) 17); 
+
+    xmlrpc_registry_set_default_method(&env, registryP, &test_default,
+                                       FOO_USER_DATA);
+    TEST_NO_FAULT(&env);
+    doRpc(&env, registryP, "test.nosuch", argArrayP, &valueP);
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+    xmlrpc_decompose_value(&env, valueP, "i", &i);
+    xmlrpc_DECREF(valueP);
+    TEST_NO_FAULT(&env);
+    TEST(i == 84);
+
+    /* Change the default method. */
+    xmlrpc_registry_set_default_method(&env, registryP, &test_default,
+                                       BAR_USER_DATA);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_DECREF(argArrayP);
+
+    xmlrpc_env_clean(&env);
+
+    printf("\n");
+}
+
+
+
+void
+test_method_registry(void) {
+
+    xmlrpc_env env, env2;
+    xmlrpc_value * valueP;
+    xmlrpc_registry *registryP;
+    xmlrpc_mem_block *response;
+
+    xmlrpc_env_init(&env);
+
+    printf("Running method registry tests.");
+
+    /* Create a new registry. */
+    registryP = xmlrpc_registry_new(&env);
+    TEST_NO_FAULT(&env);
+    TEST(registryP != NULL);
+
+    /* Add some test methods. */
+    xmlrpc_registry_add_method(&env, registryP, NULL, "test.foo",
+                               test_foo, FOO_USER_DATA);
+    TEST_NO_FAULT(&env);
+    xmlrpc_registry_add_method(&env, registryP, NULL, "test.bar",
+                               test_bar, BAR_USER_DATA);
+    TEST_NO_FAULT(&env);
+
+    printf("\n");
+    testCall(registryP);
+
+    test_system_multicall(registryP);
+
+    /* PASS bogus XML data and make sure our parser pukes gracefully.
+    ** (Because of the way the code is laid out, and the presence of other
+    ** test suites, this lets us skip tests for invalid XML-RPC data.) */
+    xmlrpc_env_init(&env2);
+    response = xmlrpc_registry_process_call(&env, registryP, NULL,
+                                            expat_error_data,
+                                            strlen(expat_error_data));
+    TEST_NO_FAULT(&env);
+    TEST(response != NULL);
+    valueP = xmlrpc_parse_response(&env2, xmlrpc_mem_block_contents(response),
+                                  xmlrpc_mem_block_size(response));
+    TEST(valueP == NULL);
+    TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+    xmlrpc_mem_block_free(response);
+    xmlrpc_env_clean(&env2);
+
+    printf("\n");
+    testDefaultMethod(registryP);
+
+    test_signature();
+    
+    /* Test cleanup code (w/memprof). */
+    xmlrpc_registry_free(registryP);
+
+    printf("\n");
+
+    xmlrpc_env_clean(&env);
+}
+
diff --git a/src/test/method_registry.h b/src/test/method_registry.h
new file mode 100644 (file)
index 0000000..bdc325b
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef TEST_METHOD_REGISTRY_H_INCLUDED
+#define TEST_METHOD_REGISTRY_H_INCLUDED
+
+void
+test_method_registry(void);
+
+#endif
diff --git a/src/test/parse_xml.c b/src/test/parse_xml.c
new file mode 100644 (file)
index 0000000..8643efd
--- /dev/null
@@ -0,0 +1,388 @@
+#include <limits.h>
+#include <stdlib.h>
+
+#include "xmlrpc_config.h"
+
+#include "girstring.h"
+#include "casprintf.h"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/xmlparser.h"
+
+#include "test.h"
+#include "xml_data.h"
+#include "parse_xml.h"
+
+
+
+static void test_expat (void)
+{
+    xmlrpc_env env;
+    xml_element *elem, *array, *data, *value1, *i4;
+    char *cdata;
+    size_t size;
+
+    xmlrpc_env_init(&env);
+
+    /* Parse a moderately complex XML document. */
+    xml_parse(&env, expat_data, strlen(expat_data), &elem);
+    TEST_NO_FAULT(&env);
+    TEST(elem != NULL);
+
+    /* Verify our results. */
+    TEST(streq(xml_element_name(elem), "value"));
+    TEST(xml_element_children_size(elem) == 1);
+    array = xml_element_children(elem)[0];
+    TEST(streq(xml_element_name(array), "array"));
+    TEST(xml_element_children_size(array) == 1);
+    data = xml_element_children(array)[0];
+    TEST(streq(xml_element_name(data), "data"));
+    TEST(xml_element_children_size(data) > 1);
+    value1 = xml_element_children(data)[0];
+    TEST(streq(xml_element_name(value1), "value"));
+    TEST(xml_element_children_size(value1) == 1);
+    i4 = xml_element_children(value1)[0];
+    TEST(streq(xml_element_name(i4), "i4"));
+    TEST(xml_element_children_size(i4) == 0);
+    cdata = xml_element_cdata(i4);
+    size = xml_element_cdata_size(i4);
+    TEST(size == strlen("2147483647"));
+    TEST(memcmp(cdata, "2147483647", strlen("2147483647")) == 0);
+
+    /* Test cleanup code (w/memprof). */
+    xml_element_free(elem);
+
+    /* Test broken XML */
+    xml_parse(&env, expat_error_data, strlen(expat_error_data), &elem);
+    TEST(env.fault_occurred);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+validateParseResponseResult(xmlrpc_value * const valueP) {
+
+    xmlrpc_env env;
+
+    xmlrpc_value * s;
+    xmlrpc_int32 int_max;
+    xmlrpc_int32 int_min;
+    xmlrpc_int32 int_one;
+    xmlrpc_bool bool_false;
+    xmlrpc_bool bool_true;
+    char * str_hello;
+    char * str_untagged;
+    char * datetime;
+    unsigned char * b64_data;
+    size_t b64_len;
+    double negone;
+    double zero;
+    double one;
+
+    xmlrpc_env_init(&env);
+
+    xmlrpc_decompose_value(
+        &env, valueP, "((iibbs68())idddSs)", 
+        &int_max, &int_min,
+        &bool_false, &bool_true, &str_hello,
+        &b64_data, &b64_len, &datetime,
+        &int_one, &negone, &zero, &one, &s, &str_untagged);
+
+    TEST_NO_FAULT(&env);
+    TEST(int_max == INT_MAX);
+    TEST(int_min == INT_MIN);
+    TEST(!bool_false);
+    TEST(bool_true);
+    TEST(strlen(str_hello) == strlen("Hello, world! <&>"));
+    TEST(streq(str_hello, "Hello, world! <&>"));
+    TEST(b64_len == 11);
+    TEST(memcmp(b64_data, "base64 data", b64_len) == 0);
+    TEST(streq(datetime, "19980717T14:08:55"));
+    TEST(int_one == 1);
+    TEST(negone == -1.0);
+    TEST(zero == 0.0);
+    TEST(one == 1.0);
+    TEST(streq(str_untagged, "Untagged string"));
+    free(str_hello);
+    free(b64_data);
+    free(datetime);
+    free(str_untagged);
+
+    {
+        /* Analyze the contents of our struct. */
+
+        xmlrpc_value * sval;
+        int size, sval_int;
+
+        TEST(s != NULL);
+        size = xmlrpc_struct_size(&env, s);
+        TEST_NO_FAULT(&env);
+        TEST(size == 2);
+        sval = xmlrpc_struct_get_value(&env, s, "ten <&>");
+        TEST_NO_FAULT(&env);
+        xmlrpc_decompose_value(&env, sval, "i", &sval_int);
+        TEST_NO_FAULT(&env);
+        TEST(sval_int == 10);
+        sval = xmlrpc_struct_get_value(&env, s, "twenty");
+        TEST_NO_FAULT(&env);
+        xmlrpc_decompose_value(&env, sval, "i", &sval_int);
+        TEST_NO_FAULT(&env);
+        TEST(sval_int == 20);
+        xmlrpc_DECREF(s);
+    }    
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testParseGoodResponse(void) {
+
+    xmlrpc_env env;
+    xmlrpc_value * valueP;
+    int faultCode;
+    const char * faultString;
+
+    xmlrpc_env_init(&env);
+
+    xmlrpc_parse_response2(&env, good_response_xml, strlen(good_response_xml),
+                           &valueP, &faultCode, &faultString);
+
+    TEST_NO_FAULT(&env);
+    TEST(faultString == NULL);
+
+    validateParseResponseResult(valueP);
+
+    xmlrpc_DECREF(valueP);
+
+    /* Try it again with old interface */
+
+    valueP = xmlrpc_parse_response(&env,
+                                   good_response_xml,
+                                   strlen(good_response_xml));
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+
+    validateParseResponseResult(valueP);
+
+    xmlrpc_DECREF(valueP);
+
+    xmlrpc_env_clean(&env);
+
+}    
+
+
+
+static void
+testParseBadResponse(void) {
+/*----------------------------------------------------------------------------
+   Test parsing of data that is supposed to be a response, but is not
+   valid.  Either not valid XML or not valid XML-RPC.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+
+    {
+        xmlrpc_env env;
+        xmlrpc_value * valueP;
+        int faultCode;
+        const char * faultString;
+
+        /* First, test some poorly-formed XML data. */
+        xmlrpc_env_init(&env);
+       
+        xmlrpc_parse_response2(&env,
+                               unparseable_value, strlen(unparseable_value),
+                               &valueP, &faultCode, &faultString);
+        
+        TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+        xmlrpc_env_clean(&env);
+
+        xmlrpc_env_init(&env);
+
+        /* And again with the old interface */
+        valueP = xmlrpc_parse_response(&env, unparseable_value,
+                                       strlen(unparseable_value));
+        TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+        xmlrpc_env_clean(&env);
+        TEST(valueP == NULL);
+    }
+
+    /* Try with good XML, but bad XML-RPC.  For this test, we test up to
+       but not including the <value> in a successful RPC response.
+    */
+
+    /* Next, check for bogus responses. These are all well-formed XML, but
+    ** they aren't legal XML-RPC. */
+    for (i = 15; bad_responses[i] != NULL; ++i) {
+        const char * const bad_resp = bad_responses[i];
+        xmlrpc_env env;
+        xmlrpc_value * v;
+        xml_element *elem;
+
+        xmlrpc_env_init(&env);
+    
+        /* First, check to make sure that our test case is well-formed XML.
+        ** (It's easy to make mistakes when writing the test cases!) */
+        xml_parse(&env, bad_resp, strlen(bad_resp), &elem);
+        TEST_NO_FAULT(&env);
+        xml_element_free(elem);
+    
+        /* Now, make sure the higher-level routine barfs appropriately. */
+        v = xmlrpc_parse_response(&env, bad_resp, strlen(bad_resp));
+        TEST(env.fault_occurred);
+        TEST(env.fault_code != 0); /* We use 0 as a code in our bad faults. */
+        TEST(v == NULL);
+        xmlrpc_env_clean(&env);
+    }
+    
+    /* Try with good XML, good XML-RPC response, except that the value
+       isn't valid XML-RPC
+    */
+    for (i = 0; bad_values[i] != NULL; ++i) {
+        const char * const bad_resp = bad_values[i];
+        xmlrpc_env env;
+        xmlrpc_value * valueP;
+        xml_element *elem;
+        int faultCode;
+        const char * faultString;
+    
+        xmlrpc_env_init(&env);
+
+        /* First, check to make sure that our test case is well-formed XML.
+        ** (It's easy to make mistakes when writing the test cases!) */
+        xml_parse(&env, bad_resp, strlen(bad_resp), &elem);
+        TEST_NO_FAULT(&env);
+        xml_element_free(elem);
+    
+        /* Now, make sure the higher-level routine barfs appropriately. */
+        
+        xmlrpc_parse_response2(&env, bad_resp, strlen(bad_resp),
+                               &valueP, &faultCode, &faultString);
+
+        TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+        xmlrpc_env_clean(&env);
+
+        xmlrpc_env_init(&env);
+
+        /* And again with the old interface */
+
+        valueP = xmlrpc_parse_response(&env, bad_resp, strlen(bad_resp));
+        TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+        TEST(valueP == NULL);
+        xmlrpc_env_clean(&env);
+    }
+}
+
+
+
+static void
+testParseFaultResponse(void) {
+/*----------------------------------------------------------------------------
+   Test parsing of a valid response that indicates the RPC failed.
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    {
+        xmlrpc_value * resultP;
+        int faultCode;
+        const char * faultString;
+            
+        xmlrpc_parse_response2(&env,
+                               serialized_fault, strlen(serialized_fault),
+                               &resultP, &faultCode, &faultString);
+
+        TEST_NO_FAULT(&env);
+        TEST(faultString != NULL);
+        TEST(faultCode == 6);
+        TEST(streq(faultString, "A fault occurred"));
+        strfree(faultString);
+    }
+    /* Now with the old interface */
+    {
+        xmlrpc_value * valueP;
+        xmlrpc_env fault;
+
+        /* Parse a valid fault. */
+        xmlrpc_env_init(&fault);
+        valueP = xmlrpc_parse_response(&fault, serialized_fault,
+                                       strlen(serialized_fault));
+
+        TEST(fault.fault_occurred);
+        TEST(fault.fault_code == 6);
+        TEST(streq(fault.fault_string, "A fault occurred"));
+        xmlrpc_env_clean(&fault);
+    }
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_parse_xml_call(void) {
+
+    xmlrpc_env env;
+    const char *method_name;
+    xmlrpc_value *params;
+    int i1, i2;
+    const char **bad_call;
+    xml_element *elem;
+
+    xmlrpc_env_init(&env);
+
+    /* Parse a valid call. */
+    xmlrpc_parse_call(&env, serialized_call, strlen(serialized_call),
+                      &method_name, &params);
+    TEST_NO_FAULT(&env);
+    TEST(params != NULL);
+    xmlrpc_decompose_value(&env, params, "(ii)", &i1, &i2);
+    xmlrpc_DECREF(params);    
+    TEST_NO_FAULT(&env);
+    TEST(streq(method_name, "gloom&doom"));
+    TEST(i1 == 10 && i2 == 20);
+    strfree(method_name);
+
+    /* Test some poorly-formed XML data. */
+    xmlrpc_parse_call(&env, unparseable_value, strlen(unparseable_value),
+                      &method_name, &params);
+    TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+    TEST(method_name == NULL && params == NULL);
+
+    /* Next, check for bogus values. These are all well-formed XML, but
+       they aren't legal XML-RPC.
+    */
+    for (bad_call = bad_calls; *bad_call != NULL; ++bad_call) {
+    
+        /* First, check to make sure that our test case is well-formed XML.
+        ** (It's easy to make mistakes when writing the test cases!) */
+        xml_parse(&env, *bad_call, strlen(*bad_call), &elem);
+        TEST_NO_FAULT(&env);
+        xml_element_free(elem);
+
+        /* Now, make sure the higher-level routine barfs appropriately. */
+        xmlrpc_parse_call(&env, *bad_call, strlen(*bad_call),
+                          &method_name, &params);
+        TEST_FAULT(&env, XMLRPC_PARSE_ERROR);
+        TEST(method_name == NULL && params == NULL);
+    }
+    xmlrpc_env_clean(&env);    
+}
+
+
+
+void
+test_parse_xml(void) {
+
+    printf("Running XML parsing tests.\n");
+    test_expat();
+    testParseGoodResponse();
+    testParseFaultResponse();
+    testParseBadResponse();
+    test_parse_xml_call();
+    printf("\n");
+    printf("XML parsing tests done.\n");
+}
diff --git a/src/test/parse_xml.h b/src/test/parse_xml.h
new file mode 100644 (file)
index 0000000..c392886
--- /dev/null
@@ -0,0 +1,2 @@
+void
+test_parse_xml(void);
diff --git a/src/test/req_no_params.xml b/src/test/req_no_params.xml
new file mode 100644 (file)
index 0000000..6ed51a4
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This may or may not be legal XML-RPC, but some old clients (including
+Ruby and xmlrpc-epi) send it.  This should be interpreted as a call with no
+parameters. -->
+
+<methodCall>
+  <methodName>foo</methodName>
+</methodCall>
diff --git a/src/test/serialize.c b/src/test/serialize.c
new file mode 100644 (file)
index 0000000..b578434
--- /dev/null
@@ -0,0 +1,283 @@
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+
+#include "test.h"
+#include "xml_data.h"
+#include "serialize.h"
+
+
+
+static void
+test_serialize_basic(void) {
+
+    xmlrpc_env env;
+    xmlrpc_value * v;
+    xmlrpc_mem_block *output;
+    size_t size;
+    
+    xmlrpc_env_init(&env);
+
+    /* Build a nice, messy value to serialize. We should attempt to use
+    ** use every data type except double (which doesn't serialize in a
+    ** portable manner. */
+    v = xmlrpc_build_value(&env, "(iibbs68())",
+                           (xmlrpc_int32) INT_MAX, (xmlrpc_int32) INT_MIN,
+                           (xmlrpc_bool) 0, (xmlrpc_bool) 1,
+                           "Hello, world! <&>",
+                           "base64 data", (size_t) 11,
+                           "19980717T14:08:55");
+    TEST_NO_FAULT(&env);
+    
+    /* Serialize the value. */
+    output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+    TEST_NO_FAULT(&env);
+    xmlrpc_serialize_value(&env, output, v);
+    TEST_NO_FAULT(&env);
+
+    /* Make sure we serialized the correct value. */
+    size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+    TEST(size == strlen(serialized_data));
+    TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+                serialized_data, size) == 0);
+    
+    /* (Debugging code to display the value.) */
+    /* XMLRPC_TYPED_MEM_BLOCK_APPEND(char, &env, output, "\0", 1);
+    ** TEST_NO_FAULT(&env);
+    ** printf("%s\n", XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output)); */
+
+    /* Clean up our value. */
+    XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+    xmlrpc_DECREF(v);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_serialize_double(void) {
+
+    /* Test serialize of a double.  */
+
+    xmlrpc_env env;
+    xmlrpc_value * v;
+    xmlrpc_mem_block *output;
+    char * result;
+        /* serialized result, as asciiz string */
+    size_t resultLength;
+        /* Length in characters of the serialized result */
+    float serializedValue;
+    char nextChar;
+    int itemsMatched;
+    
+    xmlrpc_env_init(&env);
+
+    /* Build a double to serialize */
+    v = xmlrpc_build_value(&env, "d", 3.14159);
+    TEST_NO_FAULT(&env);
+    
+    /* Serialize the value. */
+    output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+    TEST_NO_FAULT(&env);
+    xmlrpc_serialize_value(&env, output, v);
+    TEST_NO_FAULT(&env);
+
+    /* Make sure we serialized the correct value.  Note that because
+       doubles aren't precise, this might serialize as 3.1415899999
+       or something like that.  So we check it arithmetically.
+    */
+    resultLength = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+    result = malloc(resultLength + 1);
+
+    memcpy(result, XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output), 
+           resultLength);
+    result[resultLength] = '\0';
+    
+    itemsMatched = sscanf(result, 
+                          "<value><double>%f</double></value>\r\n%c",
+                          &serializedValue, &nextChar);
+
+    TEST(itemsMatched == 1);
+    TEST(serializedValue - 3.14159 < .000001);
+    /* We'd like to test more precision, but sscanf doesn't do doubles */
+
+    free(result);
+    
+    /* Clean up our value. */
+    XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+    xmlrpc_DECREF(v);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_serialize_struct(void) {
+
+    /* Serialize a simple struct. */
+
+    char const serialized_struct[] = 
+        "<value><struct>\r\n" \
+        "<member><name>&lt;&amp;&gt;</name>\r\n" \
+        "<value><i4>10</i4></value></member>\r\n" \
+        "</struct></value>";
+    
+    xmlrpc_env env;
+    xmlrpc_value * v;
+    xmlrpc_mem_block *output;
+    size_t size;
+    
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_build_value(&env, "{s:i}", "<&>", (xmlrpc_int32) 10);
+    TEST_NO_FAULT(&env);
+    output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+    TEST_NO_FAULT(&env);
+    xmlrpc_serialize_value(&env, output, v);
+    TEST_NO_FAULT(&env);
+
+    /* Make sure we serialized the correct value. */
+    size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+    TEST(size == strlen(serialized_struct));
+    TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+                serialized_struct, size) == 0);
+    
+    /* Clean up our struct. */
+    XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+    xmlrpc_DECREF(v);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_serialize_methodResponse(void) {
+
+    /* Serialize a methodResponse. */
+
+    char const serialized_response[] =
+        XML_PROLOGUE
+        "<methodResponse>\r\n"
+        "<params>\r\n"
+        "<param><value><i4>30</i4></value></param>\r\n"
+        "</params>\r\n"
+        "</methodResponse>\r\n";
+
+    xmlrpc_env env;
+    xmlrpc_value * v;
+    xmlrpc_mem_block *output;
+    size_t size;
+    
+    xmlrpc_env_init(&env);
+
+    output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+    TEST_NO_FAULT(&env);
+    v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 30);
+    TEST_NO_FAULT(&env);
+    xmlrpc_serialize_response(&env, output, v);
+    TEST_NO_FAULT(&env);
+
+    /* Make sure we serialized the correct value. */
+    size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+    TEST(size == strlen(serialized_response));
+    TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+                serialized_response, size) == 0);
+
+    /* Clean up our methodResponse. */
+    xmlrpc_DECREF(v);
+    XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_serialize_methodCall(void) {
+
+    /* Serialize a methodCall. */
+
+    xmlrpc_env env;
+    xmlrpc_value * v;
+    xmlrpc_mem_block *output;
+    size_t size;
+    
+    xmlrpc_env_init(&env);
+
+    output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+    TEST_NO_FAULT(&env);
+    v = xmlrpc_build_value(&env, "(ii)", (xmlrpc_int32) 10, (xmlrpc_int32) 20);
+    TEST_NO_FAULT(&env);
+    xmlrpc_serialize_call(&env, output, "gloom&doom", v);
+    TEST_NO_FAULT(&env);
+
+    /* Make sure we serialized the correct value. */
+    size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+    TEST(size == strlen(serialized_call));
+    TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+                serialized_call, size) == 0);
+
+    /* Clean up our methodCall. */
+    xmlrpc_DECREF(v);
+    XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_serialize_fault(void) {
+    /* Serialize a fault. */
+
+    xmlrpc_env env;
+    xmlrpc_env fault;
+    xmlrpc_mem_block *output;
+    size_t size;
+    
+    xmlrpc_env_init(&env);
+
+    output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, &env, 0);
+    TEST_NO_FAULT(&env);
+    xmlrpc_env_init(&fault);
+    xmlrpc_env_set_fault(&fault, 6, "A fault occurred");
+    xmlrpc_serialize_fault(&env, output, &fault);
+    TEST_NO_FAULT(&env);
+
+    /* Make sure we serialized the correct value. */
+    size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+    TEST(size == strlen(serialized_fault));
+    TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+                serialized_fault, size) == 0);
+
+    /* Clean up our fault. */
+    xmlrpc_env_clean(&fault);
+    XMLRPC_TYPED_MEM_BLOCK_FREE(char, output);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void 
+test_serialize(void) {
+
+    printf("Running serialize tests.");
+
+    test_serialize_basic();
+    test_serialize_double();
+    test_serialize_struct();
+    test_serialize_methodResponse();
+    test_serialize_methodCall();
+    test_serialize_fault();
+
+    printf("\n");
+    printf("Serialize tests done.\n");
+}
diff --git a/src/test/serialize.h b/src/test/serialize.h
new file mode 100644 (file)
index 0000000..f01ef58
--- /dev/null
@@ -0,0 +1,2 @@
+void 
+test_serialize(void);
diff --git a/src/test/server_abyss.c b/src/test/server_abyss.c
new file mode 100644 (file)
index 0000000..01f879b
--- /dev/null
@@ -0,0 +1,92 @@
+#include "unistdx.h"
+#include <stdio.h>
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "xmlrpc-c/abyss.h"
+#include "xmlrpc-c/server_abyss.h"
+
+#include "test.h"
+
+#include "server_abyss.h"
+
+
+static void
+testSetHandlers(TServer * const abyssServerP) {
+
+    xmlrpc_env env;
+    xmlrpc_registry * registryP;
+
+    xmlrpc_env_init(&env);
+
+    registryP = xmlrpc_registry_new(&env);
+    TEST_NO_FAULT(&env);
+    TEST(registryP != NULL);
+
+    xmlrpc_server_abyss_set_handler(&env, abyssServerP, "/RPC3", registryP);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_server_abyss_set_handlers2(abyssServerP, "/RPC4", registryP);
+
+    xmlrpc_registry_free(registryP);
+
+    {
+        xmlrpc_registry * registryP;
+        registryP = xmlrpc_registry_new(&env);
+        xmlrpc_server_abyss_set_handlers(abyssServerP, registryP);
+        xmlrpc_registry_free(registryP);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testServerParms(void) {
+    xmlrpc_server_abyss_parms parms;
+
+    parms.port_number = 1000;
+    parms.log_file_name = "/tmp/xmlrpc_logfile";
+    parms.keepalive_timeout = 5;
+    parms.keepalive_max_conn = 4;
+    parms.timeout = 50;
+    parms.dont_advertise = TRUE;
+    parms.uri_path = "/RPC9";
+    parms.chunk_response = TRUE;
+};
+
+
+
+void
+test_server_abyss(void) {
+
+    xmlrpc_env env;
+    TServer abyssServer;
+
+    printf("Running Abyss server tests...\n");
+
+    xmlrpc_env_init(&env);
+
+    ServerCreate(&abyssServer, "testserver", 8080, NULL, NULL);
+    
+    testSetHandlers(&abyssServer);
+
+    ServerSetKeepaliveTimeout(&abyssServer, 60);
+    ServerSetKeepaliveMaxConn(&abyssServer, 10);
+    ServerSetTimeout(&abyssServer, 0);
+    ServerSetAdvertise(&abyssServer, FALSE);
+
+    ServerFree(&abyssServer);
+
+    ServerCreateSocket(&abyssServer, "testserver", STDIN_FILENO,
+                       "/home/http", "/tmp/logfile");
+
+    ServerFree(&abyssServer);
+
+    testServerParms();
+
+    printf("\n");
+    printf("Abyss server tests done.\n");
+}
diff --git a/src/test/server_abyss.h b/src/test/server_abyss.h
new file mode 100644 (file)
index 0000000..2cd5279
--- /dev/null
@@ -0,0 +1,2 @@
+void
+test_server_abyss(void);
diff --git a/src/test/test.c b/src/test/test.c
new file mode 100644 (file)
index 0000000..80511f7
--- /dev/null
@@ -0,0 +1,741 @@
+/* Copyright information is at the end of the file. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "casprintf.h"
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+
+#include "test.h"
+#include "value.h"
+#include "serialize.h"
+#include "parse_xml.h"
+#include "cgi.h"
+#include "xml_data.h"
+#include "client.h"
+#include "server_abyss.h"
+#include "method_registry.h"
+
+/*=========================================================================
+**  Test Harness
+**=========================================================================
+**  This is a super light-weight test harness. It's vaguely inspired by
+**  Kent Beck's book on eXtreme Programming (XP)--the output is succinct,
+**  new tests can be coded quickly, and the whole thing runs in a few
+**  second's time.
+**
+**  To run the tests, type './rpctest'.
+**  To check for memory leaks, install RedHat's 'memprof' utility, and
+**  type 'memprof rpctest'.
+**
+**  If you add new tests to this file, please deallocate any data
+**  structures you use in the appropriate fashion. This allows us to test
+**  various destructor code for memory leaks.
+*/
+
+int total_tests = 0;
+int total_failures = 0;
+
+
+/*=========================================================================
+**  Test Data
+**=========================================================================
+**  Some common test data which need to be allocated at a fixed address,
+**  or which are inconvenient to allocate inline.
+*/
+
+static char* test_string_1 = "foo";
+static char* test_string_2 = "bar";
+static int test_int_array_1[5] = {1, 2, 3, 4, 5};
+static int test_int_array_2[3] = {6, 7, 8};
+static int test_int_array_3[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+
+/*=========================================================================
+**  Test Suites
+**=========================================================================
+*/
+
+static void test_env(void)
+{
+    xmlrpc_env env, env2;
+    char *s;
+
+    /* Test xmlrpc_env_init. */
+    xmlrpc_env_init(&env);
+    TEST(!env.fault_occurred);
+    TEST(env.fault_code == 0);
+    TEST(env.fault_string == NULL);
+
+    /* Test xmlrpc_set_fault. */
+    xmlrpc_env_set_fault(&env, 1, test_string_1);
+    TEST(env.fault_occurred);
+    TEST(env.fault_code == 1);
+    TEST(env.fault_string != test_string_1);
+    TEST(strcmp(env.fault_string, test_string_1) == 0);
+
+    /* Change an existing fault. */
+    xmlrpc_env_set_fault(&env, 2, test_string_2);
+    TEST(env.fault_occurred);
+    TEST(env.fault_code == 2);
+    TEST(strcmp(env.fault_string, test_string_2) == 0);    
+
+    /* Set a fault with a format string. */
+    xmlrpc_env_set_fault_formatted(&env, 3, "a%s%d", "bar", 9);
+    TEST(env.fault_occurred);
+    TEST(env.fault_code == 3);
+    TEST(strcmp(env.fault_string, "abar9") == 0);
+
+    /* Set a fault with an oversized string. */
+    s = "12345678901234567890123456789012345678901234567890";
+    xmlrpc_env_set_fault_formatted(&env, 4, "%s%s%s%s%s%s", s, s, s, s, s, s);
+    TEST(env.fault_occurred);
+    TEST(env.fault_code == 4);
+    TEST(strlen(env.fault_string) == 255);
+
+    /* Test cleanup code (with help from memprof). */
+    xmlrpc_env_clean(&env);
+
+    /* Test cleanup code on in absence of xmlrpc_env_set_fault. */
+    xmlrpc_env_init(&env2);
+    xmlrpc_env_clean(&env2);
+}
+
+static void test_mem_block (void)
+{
+    xmlrpc_env env;
+    xmlrpc_mem_block* block;
+
+    xmlrpc_mem_block* typed_heap_block;
+    xmlrpc_mem_block typed_auto_block;
+    void** typed_contents;
+
+    xmlrpc_env_init(&env);
+
+    /* Allocate a zero-size block. */
+    block = xmlrpc_mem_block_new(&env, 0);
+    TEST_NO_FAULT(&env);
+    TEST(block != NULL);
+    TEST(xmlrpc_mem_block_size(block) == 0);
+
+    /* Grow the block a little bit. */
+    xmlrpc_mem_block_resize(&env, block, strlen(test_string_1) + 1);
+    TEST_NO_FAULT(&env);
+    TEST(xmlrpc_mem_block_size(block) == strlen(test_string_1) + 1);
+    
+    /* Insert a string into the block, and resize it by large amount.
+    ** We want to cause a reallocation and copy of the block contents. */
+    strcpy(xmlrpc_mem_block_contents(block), test_string_1);
+    xmlrpc_mem_block_resize(&env, block, 10000);
+    TEST_NO_FAULT(&env);
+    TEST(xmlrpc_mem_block_size(block) == 10000);
+    TEST(strcmp(xmlrpc_mem_block_contents(block), test_string_1) == 0);
+
+    /* Test cleanup code (with help from memprof). */
+    xmlrpc_mem_block_free(block);
+    
+    /* Allocate a bigger block. */
+    block = xmlrpc_mem_block_new(&env, 128);
+    TEST_NO_FAULT(&env);
+    TEST(block != NULL);
+    TEST(xmlrpc_mem_block_size(block) == 128);
+
+    /* Test cleanup code (with help from memprof). */
+    xmlrpc_mem_block_free(block);
+
+    /* Allocate a "typed" memory block. */
+    typed_heap_block = XMLRPC_TYPED_MEM_BLOCK_NEW(void*, &env, 20);
+    TEST_NO_FAULT(&env);
+    TEST(typed_heap_block != NULL);
+    TEST(XMLRPC_TYPED_MEM_BLOCK_SIZE(void*, typed_heap_block) == 20);
+    typed_contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(void*, typed_heap_block);
+    TEST(typed_contents != NULL);
+
+    /* Resize a typed memory block. */
+    XMLRPC_TYPED_MEM_BLOCK_RESIZE(void*, &env, typed_heap_block, 100);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPED_MEM_BLOCK_SIZE(void*, typed_heap_block) == 100);
+
+    /* Test cleanup code (with help from memprof). */
+    XMLRPC_TYPED_MEM_BLOCK_FREE(void*, typed_heap_block);
+
+    /* Test _INIT and _CLEAN for stack-based memory blocks. */
+    XMLRPC_TYPED_MEM_BLOCK_INIT(void*, &env, &typed_auto_block, 30);
+    TEST(XMLRPC_TYPED_MEM_BLOCK_SIZE(void*, &typed_auto_block) == 30);
+    XMLRPC_TYPED_MEM_BLOCK_CLEAN(void*, &typed_auto_block);
+
+    /* Test xmlrpc_mem_block_append. */
+    block = XMLRPC_TYPED_MEM_BLOCK_NEW(int, &env, 5);
+    TEST_NO_FAULT(&env);
+    memcpy(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(int, block),
+           test_int_array_1, sizeof(test_int_array_1));
+    XMLRPC_TYPED_MEM_BLOCK_APPEND(int, &env, block, test_int_array_2, 3);
+    TEST(XMLRPC_TYPED_MEM_BLOCK_SIZE(int, block) == 8);
+    TEST(memcmp(XMLRPC_TYPED_MEM_BLOCK_CONTENTS(int, block),
+                test_int_array_3, sizeof(test_int_array_3)) == 0);
+    XMLRPC_TYPED_MEM_BLOCK_FREE(int, block);
+
+    xmlrpc_env_clean(&env);
+}
+
+static char *(base64_triplets[]) = {
+    "", "", "\r\n",
+    "a", "YQ==", "YQ==\r\n",
+    "aa", "YWE=", "YWE=\r\n",
+    "aaa", "YWFh", "YWFh\r\n",
+    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
+    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY"
+    "2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=",
+    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY"
+    "2Rl\r\n"
+    "ZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=\r\n",
+    NULL};
+
+static void
+test_base64_conversion(void) {
+    xmlrpc_env env;
+    char ** triplet;
+
+    xmlrpc_env_init(&env);
+
+    for (triplet = base64_triplets; *triplet != NULL; triplet += 3) {
+        char * bin_data;
+        char * nocrlf_ascii_data;
+        char * ascii_data;
+        xmlrpc_mem_block * output;
+
+        bin_data = *triplet;
+        nocrlf_ascii_data = *(triplet + 1);
+        ascii_data = *(triplet + 2);
+
+        /* Test our encoding routine. */
+        output = xmlrpc_base64_encode(&env,
+                                      (unsigned char*) bin_data,
+                                      strlen(bin_data));
+        TEST_NO_FAULT(&env);
+        TEST(output != NULL);
+        TEST(xmlrpc_mem_block_size(output) == strlen(ascii_data));
+        TEST(memcmp(xmlrpc_mem_block_contents(output), ascii_data,
+                    strlen(ascii_data)) == 0);
+        xmlrpc_mem_block_free(output);
+
+        /* Test our newline-free encoding routine. */
+        output =
+            xmlrpc_base64_encode_without_newlines(&env,
+                                                  (unsigned char*) bin_data,
+                                                  strlen(bin_data));
+        TEST_NO_FAULT(&env);
+        TEST(output != NULL);
+        TEST(xmlrpc_mem_block_size(output) == strlen(nocrlf_ascii_data));
+        TEST(memcmp(xmlrpc_mem_block_contents(output), nocrlf_ascii_data,
+                    strlen(nocrlf_ascii_data)) == 0);
+        xmlrpc_mem_block_free(output);
+
+        /* Test our decoding routine. */
+        output = xmlrpc_base64_decode(&env, ascii_data, strlen(ascii_data));
+        TEST_NO_FAULT(&env);
+        TEST(output != NULL);
+        TEST(xmlrpc_mem_block_size(output) == strlen(bin_data));
+        TEST(memcmp(xmlrpc_mem_block_contents(output), bin_data,
+                    strlen(bin_data)) == 0);
+        xmlrpc_mem_block_free(output);
+    }
+
+    /* Now for something broken... */
+    {
+        xmlrpc_env env2;
+        xmlrpc_mem_block * output;
+
+        xmlrpc_env_init(&env2);
+        output = xmlrpc_base64_decode(&env2, "====", 4);
+        TEST(output == NULL);
+        TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+        xmlrpc_env_clean(&env2);
+    }
+    /* Now for something broken in a really sneaky way... */
+    {
+        xmlrpc_env env2;
+        xmlrpc_mem_block * output;
+        xmlrpc_env_init(&env2);
+        output = xmlrpc_base64_decode(&env2, "a==", 4);
+        TEST(output == NULL);
+        TEST_FAULT(&env2, XMLRPC_PARSE_ERROR);
+        xmlrpc_env_clean(&env2);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void test_bounds_checks (void)
+{
+    xmlrpc_env env;
+    xmlrpc_value *array;
+    int i1, i2, i3, i4;
+
+    /* Get an array to work with. */
+    xmlrpc_env_init(&env);
+    array = xmlrpc_build_value(&env, "(iii)", 100, 200, 300);
+    TEST_NO_FAULT(&env);
+    xmlrpc_env_clean(&env);
+    
+    /* Test xmlrpc_decompose_value with too few values. */
+    xmlrpc_env_init(&env);
+    xmlrpc_decompose_value(&env, array, "(iiii)", &i1, &i2, &i3, &i4);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    xmlrpc_env_clean(&env);
+
+    /* Test xmlrpc_decompose_value with too many values. */
+    xmlrpc_env_init(&env);
+    xmlrpc_decompose_value(&env, array, "(ii)", &i1, &i2, &i3, &i4);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    xmlrpc_env_clean(&env);
+
+    /* Dispose of our array. */
+    xmlrpc_DECREF(array);
+}
+
+
+
+static void test_nesting_limit (void)
+{
+    xmlrpc_env env;
+    xmlrpc_value *val;
+
+    xmlrpc_env_init(&env);
+    
+    /* Test with an adequate limit for a result value which is an
+       array which contains an element which is a struct, whose values
+       are simple: 3.
+    */
+    xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, 3);
+    val = xmlrpc_parse_response(&env,
+                                good_response_xml, strlen(good_response_xml));
+    TEST_NO_FAULT(&env);
+    TEST(val != NULL);
+    xmlrpc_DECREF(val);
+
+    /* Test with an inadequate limit. */
+    xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, 2);
+    val = xmlrpc_parse_response(&env,
+                                good_response_xml, strlen(good_response_xml));
+    TEST_FAULT(&env, XMLRPC_PARSE_ERROR); /* BREAKME - Will change. */
+    TEST(val == NULL);
+
+    /* Reset the default limit. */
+    xmlrpc_limit_set(XMLRPC_NESTING_LIMIT_ID, XMLRPC_NESTING_LIMIT_DEFAULT);
+    TEST(xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID)
+         == XMLRPC_NESTING_LIMIT_DEFAULT);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_xml_size_limit(void) {
+
+    xmlrpc_env env;
+    const char * methodName;
+    xmlrpc_value * paramsP;
+    
+    /* NOTE - This test suite only verifies the last-ditch size-checking
+       code.  There should also be matching code in all server (and
+       preferably all client) modules as well.
+    */
+
+    /* Set our XML size limit to something ridiculous. */
+    xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, 6);
+    
+    /* Attempt to parse a call. */
+    xmlrpc_env_init(&env);
+    xmlrpc_parse_call(&env, serialized_call, strlen(serialized_call),
+                      &methodName, &paramsP);
+    TEST_FAULT(&env, XMLRPC_LIMIT_EXCEEDED_ERROR);
+    xmlrpc_env_clean(&env);
+
+    {
+        xmlrpc_value * resultP;
+        int faultCode;
+        const char * faultString;
+
+        /* Attempt to parse a response. */
+        xmlrpc_env_init(&env);
+        xmlrpc_parse_response2(&env,
+                               good_response_xml, strlen(good_response_xml),
+                               &resultP, &faultCode, &faultString);
+        TEST_FAULT(&env, XMLRPC_LIMIT_EXCEEDED_ERROR);
+        xmlrpc_env_clean(&env);
+    }
+    /* Reset the default limit. */
+    xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, XMLRPC_XML_SIZE_LIMIT_DEFAULT);
+}
+
+
+
+/*=========================================================================
+**  test_sample_files
+**=========================================================================
+**  Read in a bunch of sample test files and make sure we get plausible
+**  results.
+**
+**  We use these files to test strange-but-legal encodings, illegal-but-
+**  supported encodings, etc.
+*/
+
+#define TESTDATA_DIR "data"
+
+static char *good_requests[] = {
+    TESTDATA_DIR DIRECTORY_SEPARATOR "req_out_of_order.xml",
+    TESTDATA_DIR DIRECTORY_SEPARATOR "req_no_params.xml",
+    TESTDATA_DIR DIRECTORY_SEPARATOR "req_value_name.xml",
+    NULL
+};
+
+#define MAX_SAMPLE_FILE_LEN (16 * 1024)
+
+static char file_buff [MAX_SAMPLE_FILE_LEN];
+
+static void
+read_file (char *path, char **out_data, size_t *out_size)
+{
+    FILE *f;
+    size_t bytes_read;
+
+    /* Open the file. */
+    f = fopen(path, "r");
+    if (f == NULL) {
+        /* Since this error is fairly likely to happen, give an
+        ** informative error message... */
+        fflush(stdout);
+        fprintf(stderr, "Could not open file '%s'.  errno=%d (%s)\n", 
+                path, errno, strerror(errno));
+        abort();
+    }
+    
+    /* Read in one buffer full of data, and make sure that everything
+    ** fit.  (We perform a lazy error/no-eof/zero-length-file test using
+    ** bytes_read.) */
+    bytes_read = fread(file_buff, sizeof(char), MAX_SAMPLE_FILE_LEN, f);
+    TEST(0 < bytes_read && bytes_read < MAX_SAMPLE_FILE_LEN);
+
+    /* Close the file and return our data. */
+    fclose(f);
+    *out_data = file_buff;
+    *out_size = bytes_read;
+}
+
+static void test_sample_files (void)
+{
+    xmlrpc_env env;
+    char **paths, *path;
+    char *data;
+    size_t data_len;
+    const char *method_name;
+    xmlrpc_value *params;
+
+    xmlrpc_env_init(&env);
+
+    /* Test our good requests. */
+    for (paths = good_requests; *paths != NULL; paths++) {
+        path = *paths;
+        read_file(path, &data, &data_len);
+        xmlrpc_parse_call(&env, data, data_len, &method_name, &params);
+        TEST_NO_FAULT(&env);
+        strfree(method_name);
+        xmlrpc_DECREF(params);
+    }
+
+    xmlrpc_env_clean(&env);
+}
+
+
+/*=========================================================================
+**  test_utf8_coding
+**=========================================================================
+**  We need to test our UTF-8 decoder thoroughly.  Most of these test
+**  cases are taken from the UTF-8-test.txt file by Markus Kuhn
+**  <mkuhn@acm.org>:
+**      http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+*/
+
+#if HAVE_UNICODE_WCHAR
+
+typedef struct {
+    char *utf8;
+    wchar_t wcs[16];
+} utf8_and_wcs;
+
+static utf8_and_wcs good_utf8[] = {
+
+    /* Greek 'kosme'. */
+    {"\316\272\341\275\271\317\203\316\274\316\265",
+     {0x03BA, 0x1F79, 0x03C3, 0x03BC, 0x03B5, 0}},
+
+    /* First sequences of a given length. */
+    /* '\000' is not a legal C string. */
+    {"\302\200", {0x0080, 0}},
+    {"\340\240\200", {0x0800, 0}},
+
+    /* Last sequences of a given length. */
+    {"\177", {0x007F, 0}},
+    {"\337\277", {0x07FF, 0}},
+    /* 0xFFFF is not a legal Unicode character. */
+
+    /* Other boundry conditions. */
+    {"\001", {0x0001, 0}},
+    {"\355\237\277", {0xD7FF, 0}},
+    {"\356\200\200", {0xE000, 0}},
+    {"\357\277\275", {0xFFFD, 0}},
+
+    /* Other random test cases. */
+    {"", {0}},
+    {"abc", {0x0061, 0x0062, 0x0063, 0}},
+    {"[\302\251]", {0x005B, 0x00A9, 0x005D, 0}},
+    
+    {NULL, {0}}
+};
+
+static char *(bad_utf8[]) = {
+
+    /* Continuation bytes. */
+    "\200", "\277",
+
+    /* Lonely start characters. */
+    "\300", "\300x", "\300xx",
+    "\340", "\340x", "\340xx", "\340xxx",
+
+    /* Last byte missing. */
+    "\340\200", "\340\200x", "\340\200xx",
+    "\357\277", "\357\277x", "\357\277xx",
+
+    /* Illegal bytes. */
+    "\376", "\377",
+
+    /* Overlong '/'. */
+    "\300\257", "\340\200\257",
+
+    /* Overlong ASCII NUL. */
+    "\300\200", "\340\200\200",
+
+    /* Maximum overlong sequences. */
+    "\301\277", "\340\237\277",
+
+    /* Illegal code positions. */
+    "\357\277\276", /* U+FFFE */
+    "\357\277\277", /* U+FFFF */
+
+    /* UTF-16 surrogates (unpaired and paired). */
+    "\355\240\200",
+    "\355\277\277",
+    "\355\240\200\355\260\200",
+    "\355\257\277\355\277\277",
+
+    /* Valid UCS-4 characters (we don't handle these yet).
+    ** On systems with UCS-4 or UTF-16 wchar_t values, we
+    ** may eventually handle these in some fashion. */
+    "\360\220\200\200",
+    "\370\210\200\200\200",
+    "\374\204\200\200\200\200",
+
+    NULL
+};
+#endif  /* HAVE_UNICODE_WCHAR */
+
+/* This routine is missing on certain platforms.  This implementation
+** *appears* to be correct. */
+#if 0
+#ifndef HAVE_WCSNCMP
+int wcsncmp(wchar_t *wcs1, wchar_t* wcs2, size_t len)
+{
+    size_t i;
+    /* XXX - 'unsigned long' should be 'uwchar_t'. */
+    unsigned long c1, c2;
+    for (i=0; i < len; i++) {
+        c1 = wcs1[i];
+        c2 = wcs2[i];
+        /* This clever comparison borrowed from the GNU C Library. */
+        if (c1 == 0 || c1 != c2)
+            return c1 - c2;
+    }
+    return 0;
+}
+#endif /* HAVE_WCSNCMP */
+#endif
+
+static void
+test_utf8_coding(void) {
+
+#if HAVE_UNICODE_WCHAR
+    xmlrpc_env env, env2;
+    utf8_and_wcs *good_data;
+    char **bad_data;
+    char *utf8;
+    wchar_t *wcs;
+    xmlrpc_mem_block *output;
+
+    xmlrpc_env_init(&env);
+
+    /* Test each of our valid UTF-8 sequences. */
+    for (good_data = good_utf8; good_data->utf8 != NULL; good_data++) {
+        utf8 = good_data->utf8;
+        wcs = good_data->wcs;
+
+        /* Attempt to validate the UTF-8 string. */
+        xmlrpc_validate_utf8(&env, utf8, strlen(utf8));
+        TEST_NO_FAULT(&env);
+
+        /* Attempt to decode the UTF-8 string. */
+        output = xmlrpc_utf8_to_wcs(&env, utf8, strlen(utf8));
+        TEST_NO_FAULT(&env);
+        TEST(output != NULL);
+        TEST(wcslen(wcs) == XMLRPC_TYPED_MEM_BLOCK_SIZE(wchar_t, output));
+        TEST(0 ==
+             wcsncmp(wcs, XMLRPC_TYPED_MEM_BLOCK_CONTENTS(wchar_t, output),
+                     wcslen(wcs)));
+        xmlrpc_mem_block_free(output);
+
+        /* Test the UTF-8 encoder, too. */
+        output = xmlrpc_wcs_to_utf8(&env, wcs, wcslen(wcs));
+        TEST_NO_FAULT(&env);
+        TEST(output != NULL);
+        TEST(strlen(utf8) == XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output));
+        TEST(0 ==
+             strncmp(utf8, XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output),
+                     strlen(utf8)));
+        xmlrpc_mem_block_free(output);
+    }
+
+    /* Test each of our illegal UTF-8 sequences. */
+    for (bad_data = bad_utf8; *bad_data != NULL; bad_data++) {
+        utf8 = *bad_data;
+    
+        /* Attempt to validate the UTF-8 string. */
+        xmlrpc_env_init(&env2);
+        xmlrpc_validate_utf8(&env2, utf8, strlen(utf8));
+        TEST_FAULT(&env2, XMLRPC_INVALID_UTF8_ERROR);
+        /* printf("Fault: %s\n", env2.fault_string); --Hand-checked */
+        xmlrpc_env_clean(&env2);
+
+        /* Attempt to decode the UTF-8 string. */
+        xmlrpc_env_init(&env2);
+        output = xmlrpc_utf8_to_wcs(&env2, utf8, strlen(utf8));
+        TEST_FAULT(&env2, XMLRPC_INVALID_UTF8_ERROR);
+        TEST(output == NULL);
+        xmlrpc_env_clean(&env2);
+    }
+    xmlrpc_env_clean(&env);
+#endif  /* HAVE_UNICODE_WCHAR */
+}
+
+
+
+static void
+test_server_cgi_maybe(void) {
+
+#ifndef WIN32
+
+    test_server_cgi();
+
+#endif 
+}
+
+
+
+static void
+test_client_maybe(void) {
+
+#ifndef WIN32 /* Must get Windows Curl transport working for this to work */
+
+    test_client();
+
+#endif 
+}
+
+
+
+int 
+main(int     argc, 
+     char ** argv ATTR_UNUSED) {
+
+    int retval;
+
+    if (argc-1 > 0) {
+        fprintf(stderr, "There are no arguments.");
+        retval = 1;
+    } else {
+        /* Add your test suites here. */
+        test_env();
+        test_mem_block();
+        test_base64_conversion();
+        printf("\n");
+        test_value();
+        test_bounds_checks();
+        printf("\n");
+        test_serialize();
+        test_parse_xml();
+        test_method_registry();
+        test_nesting_limit();
+        test_xml_size_limit();
+        test_sample_files();
+        printf("\n");
+        test_server_cgi_maybe();
+        test_server_abyss();
+
+        test_utf8_coding();
+
+        printf("\n");
+
+        test_client_maybe();
+
+        /* Summarize our test run. */
+        printf("\nRan %d tests, %d failed, %.1f%% passed\n",
+               total_tests, total_failures,
+               100.0 - (100.0 * total_failures) / total_tests);
+
+        /* Print the final result. */
+        if (total_failures == 0) {
+            printf("OK\n");
+            retval = 0;
+        } else {
+            retval = 1;
+            printf("FAILED\n");
+        }
+    }
+    return retval;
+}
+
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/src/test/test.h b/src/test/test.h
new file mode 100644 (file)
index 0000000..4d5bdb8
--- /dev/null
@@ -0,0 +1,75 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "xmlrpc-c/util.h"
+
+extern int total_tests;
+extern int total_failures;
+
+
+/* This is a good place to set a breakpoint. */
+static __inline__ void
+test_failure(const char * const file,
+             unsigned int const line,
+             const char * const label,
+             const char * const statement) {
+
+    ++total_failures;
+    printf("\n%s:%u: test failure: %s (%s)\n", file, line, label, statement);
+    abort();
+}
+
+
+
+#define TEST(statement) \
+do { \
+    ++total_tests; \
+    if ((statement)) { \
+        printf("."); \
+    } else { \
+        test_failure(__FILE__, __LINE__, "expected", #statement); \
+    } \
+   } while (0)
+
+#define TEST_NO_FAULT(env) \
+    do { \
+        ++total_tests; \
+        if (!(env)->fault_occurred) { \
+            printf("."); \
+        } else { \
+            test_failure(__FILE__, __LINE__, "fault occurred", \
+            (env)->fault_string); \
+        } \
+       } while (0)
+
+static inline void
+test_fault(xmlrpc_env * const envP,
+           int          const expectedCode,
+           const char * const fileName,
+           unsigned int const lineNumber) {
+
+    ++total_tests;
+    if (!envP->fault_occurred)
+        test_failure(fileName, lineNumber, "no fault occurred", "");
+    else if (envP->fault_code != expectedCode)
+        test_failure(fileName, lineNumber, "wrong fault occurred",
+                     envP->fault_string);
+    else
+        printf(".");
+
+    xmlrpc_env_clean(envP);
+    xmlrpc_env_init(envP);
+}
+
+
+#define TEST_FAULT(envP, code) \
+    do { test_fault(envP, code, __FILE__, __LINE__); } while(0)
+
+;
+
+#define TEST_ERROR(reason) \
+do { \
+    printf("Unable to test at %s/%u.  %s", __FILE__, __LINE__, reason); \
+    abort(); \
+   } while (0)
+
diff --git a/src/test/value.c b/src/test/value.c
new file mode 100644 (file)
index 0000000..8fe1885
--- /dev/null
@@ -0,0 +1,1326 @@
+/* Copyright information is at the end of the file. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "casprintf.h"
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+
+#include "test.h"
+#include "value.h"
+
+
+
+/*=========================================================================
+**  Test Data
+**=========================================================================
+**  Some common test data which need to be allocated at a fixed address,
+**  or which are inconvenient to allocate inline.
+*/
+static char* test_string_1 = "foo";
+
+
+
+static void
+test_value_alloc_dealloc(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    /* Test allocation and deallocation (w/memprof). */
+    v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 5);
+    TEST_NO_FAULT(&env);
+    TEST(v != NULL);
+    xmlrpc_INCREF(v);
+    xmlrpc_DECREF(v);
+    xmlrpc_DECREF(v);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+static void
+test_value_integer(void) { 
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    xmlrpc_int32 i;
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_int_new(&env, (xmlrpc_int32) 25);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_INT == xmlrpc_value_type(v));
+    xmlrpc_read_int(&env, v, &i);
+    TEST_NO_FAULT(&env);
+    TEST(i == 25);
+    xmlrpc_DECREF(v);
+
+    v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 10);
+    TEST_NO_FAULT(&env);
+    TEST(v != NULL);
+    TEST(XMLRPC_TYPE_INT == xmlrpc_value_type(v));
+    xmlrpc_decompose_value(&env, v, "i", &i);
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+    TEST(i == 10);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_bool(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    xmlrpc_bool b;
+
+    /* Test booleans. */
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_bool_new(&env, (xmlrpc_bool) 1);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_BOOL == xmlrpc_value_type(v));
+    xmlrpc_read_bool(&env, v, &b);
+    TEST_NO_FAULT(&env);
+    TEST(b);
+    xmlrpc_DECREF(v);
+
+    v = xmlrpc_build_value(&env, "b", (xmlrpc_bool) 0);
+    TEST_NO_FAULT(&env);
+    TEST(v != NULL);
+    TEST(XMLRPC_TYPE_BOOL == xmlrpc_value_type(v));
+    xmlrpc_decompose_value(&env, v, "b", &b);
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+    TEST(!b);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_double(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    double d;
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_double_new(&env, -3.25);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_DOUBLE == xmlrpc_value_type(v));
+    xmlrpc_read_double(&env, v, &d);
+    TEST_NO_FAULT(&env);
+    TEST(d == -3.25);
+    xmlrpc_DECREF(v);
+
+    v = xmlrpc_build_value(&env, "d", 1.0);
+    TEST_NO_FAULT(&env);
+    TEST(v != NULL);
+    TEST(XMLRPC_TYPE_DOUBLE == xmlrpc_value_type(v));
+    xmlrpc_decompose_value(&env, v, "d", &d);
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+    TEST(d == 1.0);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_datetime(void) {
+
+    const char * datestring = "19980717T14:08:55";
+    time_t const datetime = 900684535;
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    const char * ds;
+    time_t dt;
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_datetime_new_str(&env, datestring);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v));
+
+    xmlrpc_read_datetime_str(&env, v, &ds);
+    TEST_NO_FAULT(&env);
+    TEST(strcmp(ds, datestring) == 0);
+    strfree(ds);
+
+    xmlrpc_read_datetime_sec(&env, v, &dt);
+    TEST_NO_FAULT(&env);
+    TEST(dt == datetime);
+
+    xmlrpc_DECREF(v);
+
+    v = xmlrpc_datetime_new_sec(&env, datetime);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v));
+
+    xmlrpc_read_datetime_str(&env, v, &ds);
+    TEST_NO_FAULT(&env);
+    TEST(strcmp(ds, datestring) == 0);
+    strfree(ds);
+
+    xmlrpc_read_datetime_sec(&env, v, &dt);
+    TEST_NO_FAULT(&env);
+    TEST(dt == datetime);
+
+    xmlrpc_DECREF(v);
+
+    v = xmlrpc_build_value(&env, "8", datestring);
+    TEST_NO_FAULT(&env);
+    TEST(v != NULL);
+    TEST(XMLRPC_TYPE_DATETIME == xmlrpc_value_type(v));
+    xmlrpc_decompose_value(&env, v, "8", &ds);
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+    TEST(strcmp(ds, datestring) == 0);
+    strfree(ds);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_string_no_null(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    const char * str;
+    size_t len;
+
+    /* Test strings (without '\0' bytes). */
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_string_new(&env, test_string_1);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_STRING == xmlrpc_value_type(v));
+    xmlrpc_read_string(&env, v, &str);
+    TEST_NO_FAULT(&env);
+    TEST(strcmp(str, test_string_1) == 0);
+    xmlrpc_DECREF(v);
+    strfree(str);
+
+    v = xmlrpc_build_value(&env, "s", test_string_1);
+
+    TEST_NO_FAULT(&env);
+    TEST(v != NULL);
+    TEST(XMLRPC_TYPE_STRING == xmlrpc_value_type(v));
+
+    xmlrpc_decompose_value(&env, v, "s", &str);
+    TEST_NO_FAULT(&env);
+    TEST(strcmp(str, test_string_1) == 0);
+    strfree(str);
+
+    xmlrpc_decompose_value(&env, v, "s#", &str, &len);
+    TEST_NO_FAULT(&env);
+    TEST(memcmp(str, test_string_1, strlen(test_string_1)) == 0);
+    TEST(strlen(str) == strlen(test_string_1));
+    strfree(str);
+
+    xmlrpc_DECREF(v);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_string_null(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    xmlrpc_env env2;
+    const char * str;
+    size_t len;
+
+    /* Test a string with a '\0' byte. */
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_string_new_lp(&env, 7, "foo\0bar");
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_STRING == xmlrpc_value_type(v));
+    xmlrpc_read_string_lp(&env, v, &len, &str);
+    TEST_NO_FAULT(&env);
+    TEST(len == 7);
+    TEST(memcmp(str, "foo\0bar", 7) == 0);
+    xmlrpc_DECREF(v);
+    strfree(str);
+
+    v = xmlrpc_build_value(&env, "s#", "foo\0bar", (size_t) 7);
+    TEST_NO_FAULT(&env);
+    TEST(v != NULL);
+    TEST(XMLRPC_TYPE_STRING == xmlrpc_value_type(v));
+
+    xmlrpc_decompose_value(&env, v, "s#", &str, &len);
+    TEST_NO_FAULT(&env);
+    TEST(memcmp(str, "foo\0bar", 7) == 0);
+    TEST(len == 7);
+    strfree(str);
+
+    /* Test for type error when decoding a string with a zero byte to a
+    ** regular C string. */
+    xmlrpc_env_init(&env2);
+    xmlrpc_decompose_value(&env2, v, "s", &str);
+    TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
+    xmlrpc_env_clean(&env2);
+    xmlrpc_DECREF(v);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+
+/* Here is a 3-character, NUL-terminated string, once in UTF-8 chars,
+   and once in UTF-16 wchar_ts.  Note that 2 of the UTF-16 characters
+   translate directly to UTF-8 bytes because only the lower 7 bits of
+   each is nonzero, but the middle UTF-16 character translates to two
+   UTF-8 bytes.  
+*/
+static char utf8_data[] = "[\xC2\xA9]";
+static wchar_t wcs_data[] = {'[', 0x00A9, ']', 0x0000};
+
+static void
+test_value_string_wide_build(void) {
+
+    xmlrpc_env env;
+    xmlrpc_value * valueP;
+    const wchar_t * wcs;
+    size_t len;
+
+    xmlrpc_env_init(&env);
+
+    /* Build with build_value w# */
+    valueP = xmlrpc_build_value(&env, "w#", wcs_data, 3);
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+
+    /* Verify it */
+    xmlrpc_read_string_w_lp(&env, valueP, &len, &wcs);
+    TEST_NO_FAULT(&env);
+    TEST(wcs != NULL);
+    TEST(len == 3);
+    TEST(wcs[len] == '\0');
+    TEST(0 == wcsncmp(wcs, wcs_data, len));
+    free((void*)wcs);
+
+    xmlrpc_DECREF(valueP);
+
+    /* Build with build_value w */
+    valueP = xmlrpc_build_value(&env, "w", wcs_data);
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+
+    /* Verify it */
+    xmlrpc_read_string_w_lp(&env, valueP, &len, &wcs);
+    TEST_NO_FAULT(&env);
+    TEST(wcs != NULL);
+    TEST(len == 3);
+    TEST(wcs[len] == '\0');
+    TEST(0 == wcsncmp(wcs, wcs_data, len));
+    free((void*)wcs);
+
+    xmlrpc_DECREF(valueP);
+}
+#endif /* HAVE_UNICODE_WCHAR */
+
+
+static void 
+test_value_string_wide(void) {
+
+#if HAVE_UNICODE_WCHAR
+    xmlrpc_env env;
+    xmlrpc_value * valueP;
+    const wchar_t * wcs;
+    size_t len;
+
+    xmlrpc_env_init(&env);
+
+    /* Build a string from wchar_t data. */
+    valueP = xmlrpc_string_w_new_lp(&env, 3, wcs_data);
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+
+    /* Extract it as a wchar_t string. */
+    xmlrpc_read_string_w_lp(&env, valueP, &len, &wcs);
+    TEST_NO_FAULT(&env);
+    TEST(wcs != NULL);
+    TEST(len == 3);
+    TEST(wcs[len] == '\0');
+    TEST(0 == wcsncmp(wcs, wcs_data, len));
+    free((void*)wcs);
+
+    xmlrpc_read_string_w(&env, valueP, &wcs);
+    TEST_NO_FAULT(&env);
+    TEST(wcs != NULL);
+    TEST(wcs[3] == '\0');
+    TEST(0 == wcsncmp(wcs, wcs_data, 3));
+    free((void*)wcs);
+
+    xmlrpc_decompose_value(&env, valueP, "w#", &wcs, &len);
+    TEST_NO_FAULT(&env);
+    TEST(wcs != NULL);
+    TEST(len == 3);
+    TEST(wcs[len] == '\0');
+    TEST(0 == wcsncmp(wcs, wcs_data, len));
+    free((void*)wcs);
+
+    {
+        /* Extract it as a UTF-8 string. */
+        const char * str;
+        size_t len;
+
+        xmlrpc_read_string_lp(&env, valueP, &len, &str);
+        TEST_NO_FAULT(&env);
+        TEST(str != NULL);
+        TEST(len == 4);
+        TEST(str[len] == '\0');
+        TEST(0 == strncmp(str, utf8_data, len));
+        free((void*)str);
+    }
+
+    xmlrpc_DECREF(valueP);
+
+    /* Build from null-terminated wchar_t string */
+    valueP = xmlrpc_string_w_new(&env, wcs_data);
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+
+    /* Verify it */
+    xmlrpc_read_string_w_lp(&env, valueP, &len, &wcs);
+    TEST_NO_FAULT(&env);
+    TEST(wcs != NULL);
+    TEST(len == 3);
+    TEST(wcs[len] == '\0');
+    TEST(0 == wcsncmp(wcs, wcs_data, len));
+    free((void*)wcs);
+
+    xmlrpc_DECREF(valueP);
+
+    test_value_string_wide_build();
+
+    /* Build a string from UTF-8 data. */
+    valueP = xmlrpc_string_new(&env, utf8_data);
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+
+    /* Extract it as a wchar_t string. */
+    xmlrpc_read_string_w_lp(&env, valueP, &len, &wcs);
+    TEST_NO_FAULT(&env);
+    TEST(wcs != NULL);
+    TEST(len == 3);
+    TEST(wcs[len] == 0x0000);
+    TEST(0 == wcsncmp(wcs, wcs_data, len));
+    free((void*)wcs);
+    xmlrpc_DECREF(valueP);
+
+    /* Test with embedded NUL.  We use a length of 4 so that the terminating
+       NUL actually becomes part of the string.
+    */
+    valueP = xmlrpc_string_w_new_lp(&env, 4, wcs_data);
+    TEST_NO_FAULT(&env);
+    TEST(valueP != NULL);
+
+    /* Extract it as a wchar_t string. */
+    xmlrpc_read_string_w_lp(&env, valueP, &len, &wcs);
+    TEST_NO_FAULT(&env);
+    TEST(wcs != NULL);
+    TEST(len == 4);
+    TEST(wcs[len] == '\0');
+    TEST(0 == wcsncmp(wcs, wcs_data, len));
+    free((void*)wcs);
+
+    xmlrpc_read_string_w(&env, valueP, &wcs);
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+    xmlrpc_DECREF(valueP);
+#endif /* HAVE_UNICODE_WCHAR */
+}
+
+
+
+static void
+test_value_base64(void) {
+
+    /* Test <base64> data. */
+
+    unsigned char const data1[5] = {'a', '\0', 'b', '\n', 'c'};
+    unsigned char const data2[3] = {'a', '\0', 'b'};
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    const unsigned char * data;
+    size_t len;
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_base64_new(&env, sizeof(data1), data1);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_BASE64 == xmlrpc_value_type(v));
+    xmlrpc_read_base64(&env, v, &len, &data);
+    TEST_NO_FAULT(&env);
+    TEST(memcmp(data, data1, sizeof(data1)) == 0);
+    TEST(len == sizeof(data1));
+    xmlrpc_DECREF(v);
+    free((void*)data);
+
+    v = xmlrpc_build_value(&env, "6", data2, sizeof(data2));
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_BASE64 == xmlrpc_value_type(v));
+    xmlrpc_decompose_value(&env, v, "6", &data, &len);
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+    TEST(len == sizeof(data2));
+    TEST(memcmp(data, data1, sizeof(data2)) == 0);
+    strfree(data);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_value(void) {
+
+    xmlrpc_value *v, *v2, *v3;
+    xmlrpc_env env;
+
+    /* Test 'V' with building and parsing. */
+
+    xmlrpc_env_init(&env);
+
+    v2 = xmlrpc_int_new(&env, (xmlrpc_int32) 5);
+    TEST_NO_FAULT(&env);
+    v = xmlrpc_build_value(&env, "V", v2);
+    TEST_NO_FAULT(&env);
+    TEST(v == v2);
+    xmlrpc_decompose_value(&env, v2, "V", &v3);
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+    TEST(v2 == v3);
+    xmlrpc_DECREF(v3);
+    xmlrpc_DECREF(v2);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_array(void) {
+
+    xmlrpc_value *v;
+    xmlrpc_env env;
+    size_t len;
+
+    /* Basic array-building test. */
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_array_new(&env);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(v));
+    len = xmlrpc_array_size(&env, v);
+    TEST_NO_FAULT(&env);
+    TEST(len == 0);
+    xmlrpc_DECREF(v);
+
+    v = xmlrpc_build_value(&env, "()");
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(v));
+    len = xmlrpc_array_size(&env, v);
+    TEST_NO_FAULT(&env);
+    TEST(len == 0);
+    xmlrpc_DECREF(v);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_AS(void) {
+
+    xmlrpc_value *v;
+    xmlrpc_value *v2;
+    xmlrpc_value *v3;
+    xmlrpc_env env;
+    size_t len;
+
+    /* Test parsing of 'A' and 'S'. */
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_build_value(&env, "((){})");
+    TEST_NO_FAULT(&env);
+    xmlrpc_decompose_value(&env, v, "(AS)", &v2, &v3);
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(v2));
+    TEST(XMLRPC_TYPE_STRUCT == xmlrpc_value_type(v3));
+    len = xmlrpc_array_size(&env, v2);
+    TEST_NO_FAULT(&env);
+    TEST(len == 0);
+    len = xmlrpc_struct_size(&env, v3);
+    TEST_NO_FAULT(&env);
+    TEST(len == 0);
+    xmlrpc_DECREF(v2);
+    xmlrpc_DECREF(v3);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_AS_typecheck(void) {
+
+    xmlrpc_env env;
+    xmlrpc_env env2;
+    xmlrpc_value *v;
+    xmlrpc_value *v2;
+
+    /* Test typechecks for 'A' and 'S'. */
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_build_value(&env, "s", "foo");
+    TEST_NO_FAULT(&env);
+    xmlrpc_env_init(&env2);
+    xmlrpc_decompose_value(&env2, v, "A", &v2);
+    TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
+    xmlrpc_env_clean(&env2);
+
+    xmlrpc_env_init(&env2);
+    xmlrpc_decompose_value(&env2, v, "S", &v2);
+    TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
+    xmlrpc_env_clean(&env2);
+    xmlrpc_DECREF(v);
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_array2(void) {
+
+    xmlrpc_value * arrayP;
+    xmlrpc_env env;
+    xmlrpc_int32 i, i1, i2, i3, i4;
+    xmlrpc_value * itemP;
+    xmlrpc_value * subarrayP;
+    size_t len;
+
+    /* A more complex array. */
+
+    xmlrpc_env_init(&env);
+
+    arrayP = xmlrpc_build_value(&env, "(i(ii)i)",
+                                (xmlrpc_int32) 10, (xmlrpc_int32) 20,
+                                (xmlrpc_int32) 30, (xmlrpc_int32) 40);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(arrayP));
+
+    len = xmlrpc_array_size(&env, arrayP);
+    TEST_NO_FAULT(&env);
+    TEST(len == 3);
+
+    xmlrpc_array_read_item(&env, arrayP, 1, &subarrayP);
+    TEST_NO_FAULT(&env);
+
+    len = xmlrpc_array_size(&env, subarrayP);
+    TEST_NO_FAULT(&env);
+    TEST(len == 2);
+
+    xmlrpc_array_read_item(&env, subarrayP, 0, &itemP);
+    TEST_NO_FAULT(&env);
+    xmlrpc_decompose_value(&env, itemP, "i", &i);
+    xmlrpc_DECREF(itemP);
+    TEST_NO_FAULT(&env);
+    TEST(i == 20);
+
+    xmlrpc_DECREF(subarrayP);
+
+    itemP = xmlrpc_array_get_item(&env, arrayP, 0);
+    TEST_NO_FAULT(&env);
+    xmlrpc_decompose_value(&env, itemP, "i", &i);
+    TEST_NO_FAULT(&env);
+    TEST(i == 10);
+
+    xmlrpc_decompose_value(&env, arrayP, "(i(ii)i)", &i1, &i2, &i3, &i4);
+    TEST_NO_FAULT(&env);
+    TEST(i1 == 10 && i2 == 20 && i3 == 30 && i4 == 40);
+
+    xmlrpc_decompose_value(&env, arrayP, "(i(i*)i)", &i1, &i2, &i3);
+    TEST_NO_FAULT(&env);
+    TEST(i1 == 10 && i2 == 20 && i3 == 40);
+
+    xmlrpc_decompose_value(&env, arrayP, "(i(ii*)i)", &i1, &i2, &i3, &i4);
+    TEST_NO_FAULT(&env);
+
+
+    /* Test bounds check on xmlrpc_array_get_item. */
+    xmlrpc_array_read_item(&env, arrayP, 3, &itemP);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    xmlrpc_env_clean(&env);
+    xmlrpc_env_init(&env);
+
+    xmlrpc_array_get_item(&env, arrayP, 3);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    xmlrpc_env_clean(&env);
+    xmlrpc_env_init(&env);
+
+    xmlrpc_array_get_item(&env, arrayP, -1);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    xmlrpc_env_clean(&env);
+    xmlrpc_env_init(&env);
+
+    xmlrpc_DECREF(arrayP);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_array_nil(void) {
+
+    xmlrpc_value * arrayP;
+    xmlrpc_env env;
+    xmlrpc_int32 i1, i2;
+    xmlrpc_value * itemP;
+    size_t len;
+
+    xmlrpc_env_init(&env);
+
+    arrayP = xmlrpc_build_value(&env, "(nini)",
+                                (xmlrpc_int32) 10, (xmlrpc_int32) 20);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(arrayP));
+
+    len = xmlrpc_array_size(&env, arrayP);
+    TEST_NO_FAULT(&env);
+    TEST(len == 4);
+
+    itemP = xmlrpc_array_get_item(&env, arrayP, 0);
+    TEST_NO_FAULT(&env);
+    xmlrpc_decompose_value(&env, itemP, "n");
+    TEST_NO_FAULT(&env);
+
+    itemP = xmlrpc_array_get_item(&env, arrayP, 1);
+    TEST_NO_FAULT(&env);
+    {
+        int i;
+        xmlrpc_decompose_value(&env, itemP, "i", &i);
+        TEST_NO_FAULT(&env);
+        TEST(i == 10);
+    }
+    xmlrpc_decompose_value(&env, arrayP, "(nini)", &i1, &i2);
+    TEST_NO_FAULT(&env);
+    TEST(i1 == 10 && i2 == 20);
+
+    /* Test bounds check on xmlrpc_array_get_item. */
+    xmlrpc_array_read_item(&env, arrayP, 4, &itemP);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    xmlrpc_env_clean(&env);
+    xmlrpc_env_init(&env);
+
+    xmlrpc_array_get_item(&env, arrayP, 4);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    xmlrpc_env_clean(&env);
+    xmlrpc_env_init(&env);
+
+    xmlrpc_DECREF(arrayP);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_type_mismatch(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    xmlrpc_env env2;
+    char * str;
+
+    /* Test for one, simple kind of type mismatch error. We assume that
+    ** if one of these typechecks works, the rest work fine. */
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_build_value(&env, "i", (xmlrpc_int32) 5);
+    TEST_NO_FAULT(&env);
+    xmlrpc_env_init(&env2);
+    xmlrpc_decompose_value(&env2, v, "s", &str);
+    xmlrpc_DECREF(v);
+    TEST_FAULT(&env2, XMLRPC_TYPE_ERROR);
+    xmlrpc_env_clean(&env2);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_cptr(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    void * ptr;
+
+    /* Test C pointer storage using 'p'.
+       We don't have cleanup functions (yet). 
+    */
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_build_value(&env, "p", (void*) 0x00000017);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_C_PTR == xmlrpc_value_type(v));
+    xmlrpc_decompose_value(&env, v, "p", &ptr);
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+    TEST(ptr == (void*) 0x00000017);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_nil(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_nil_new(&env);
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_NIL == xmlrpc_value_type(v));
+    xmlrpc_DECREF(v);
+
+    v = xmlrpc_build_value(&env, "n");
+    TEST_NO_FAULT(&env);
+    TEST(XMLRPC_TYPE_NIL == xmlrpc_value_type(v));
+    xmlrpc_decompose_value(&env, v, "n");
+    xmlrpc_DECREF(v);
+    TEST_NO_FAULT(&env);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_invalid_type(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+
+    /* Test invalid type specifier in format string */
+
+    xmlrpc_env_init(&env);
+
+    v = xmlrpc_build_value(&env, "Q");
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_missing_array_delim(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+
+    /* Test missing close parenthesis on array */
+
+    xmlrpc_env_init(&env);
+    v = xmlrpc_build_value(&env, "(");
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+    xmlrpc_env_clean(&env);
+
+    xmlrpc_env_init(&env);
+    v = xmlrpc_build_value(&env, "(i");
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_missing_struct_delim(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+    
+    /* Test missing closing brace on struct */
+
+    xmlrpc_env_init(&env);
+    v = xmlrpc_build_value(&env, "{");
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+    xmlrpc_env_clean(&env);
+
+    xmlrpc_env_init(&env);
+    v = xmlrpc_build_value(&env, "{s:i", "key1", 7);
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+    xmlrpc_env_clean(&env);
+
+    xmlrpc_env_init(&env);
+    v = xmlrpc_build_value(&env, "{s:i,s:i", "key1", 9, "key2", -4);
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_invalid_struct(void) {
+
+    xmlrpc_value * v;
+    xmlrpc_env env;
+
+    /* Note that even though the format strings are invalid, we have
+       to supply the variable arguments that xmlrpc_build_value() will
+       be looking for as it tries to parse it.  Otherwise, we get wild
+       memory references and consequent Valgrind flags.
+    */
+    
+    xmlrpc_env_init(&env);
+    v = xmlrpc_build_value(&env, "{s:ii", "key1", 9, 9);
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+    xmlrpc_env_clean(&env);
+
+    xmlrpc_env_init(&env);
+    v = xmlrpc_build_value(&env, "{si:", "key1", 9);
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+    xmlrpc_env_clean(&env);
+
+    xmlrpc_env_init(&env);
+    v = xmlrpc_build_value(&env, "{s", "key1");
+    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_value_parse_value(void) {
+
+    xmlrpc_env env;
+    xmlrpc_value * valueP;
+    const char * datestring = "19980717T14:08:55";
+
+    xmlrpc_env_init(&env);
+
+    valueP = xmlrpc_build_value(&env, "(idb8ss#6(i){s:i}np(i))",
+                                7, 3.14, (xmlrpc_bool)1, datestring,
+                                "hello world", "a\0b", 3, 
+                                "base64 data", strlen("base64 data"),
+                                15, "member9", 9, &valueP, -5);
+    
+    TEST_NO_FAULT(&env);
+
+    {
+        xmlrpc_int32 i;
+        xmlrpc_double d;
+        xmlrpc_bool b;
+        const char * dt_str;
+        const char * s1;
+        const char * s2;
+        size_t s2_len;
+        const unsigned char * b64;
+        size_t b64_len;
+        xmlrpc_value * arrayP;
+        xmlrpc_value * structP;
+        void * cptr;
+        xmlrpc_value * subvalP;
+
+        xmlrpc_parse_value(&env, valueP, "(idb8ss#6ASnpV)",
+                           &i, &d, &b, &dt_str, &s1, &s2, &s2_len,
+                           &b64, &b64_len,
+                           &arrayP, &structP, &cptr, &subvalP);
+        
+        TEST_NO_FAULT(&env);
+
+        TEST(i == 7);
+        TEST(d == 3.14);
+        TEST(b == (xmlrpc_bool)1);
+        TEST(strcmp(dt_str, datestring) == 0);
+        TEST(strcmp(s1, "hello world") == 0);
+        TEST(s2_len == 3);
+        TEST(memcmp(s2, "a\0b", 3) == 0);
+        TEST(b64_len == strlen("base64 data"));
+        TEST(memcmp(b64, "base64 data", b64_len) == 0);
+        TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(arrayP));
+        TEST(XMLRPC_TYPE_STRUCT == xmlrpc_value_type(structP));
+        TEST(cptr == &valueP);
+        TEST(XMLRPC_TYPE_ARRAY == xmlrpc_value_type(subvalP));
+
+        xmlrpc_DECREF(valueP);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_struct_get_element(xmlrpc_value * const structP,
+                        xmlrpc_value * const i1,
+                        xmlrpc_value * const i2,
+                        const char *   const weirdKey,
+                        unsigned int   const weirdKeyLen) {
+
+    xmlrpc_env env;
+    xmlrpc_value * valueP;
+    xmlrpc_value * aasStringP;
+    xmlrpc_value * bogusKeyStringP;
+
+    xmlrpc_env_init(&env);
+
+    /* build test tools */
+
+    aasStringP = xmlrpc_build_value(&env, "s", "aas");
+    TEST_NO_FAULT(&env);
+
+    bogusKeyStringP = xmlrpc_build_value(&env, "s", "doesn't_exist");
+    TEST_NO_FAULT(&env);
+
+    /* "find" interface */
+
+    xmlrpc_struct_find_value(&env, structP, "aas", &valueP);
+    TEST_NO_FAULT(&env);
+    TEST(valueP == i1);
+    xmlrpc_DECREF(valueP);
+            
+    xmlrpc_struct_find_value(&env, structP, "doesn't_exist", &valueP);
+    TEST_NO_FAULT(&env);
+    TEST(valueP == NULL);
+            
+    xmlrpc_struct_find_value_v(&env, structP, aasStringP, &valueP);
+    TEST_NO_FAULT(&env);
+    TEST(valueP == i1);
+    xmlrpc_DECREF(valueP);
+            
+    xmlrpc_struct_find_value_v(&env, structP, bogusKeyStringP, &valueP);
+    TEST_NO_FAULT(&env);
+    TEST(valueP == NULL);
+
+    xmlrpc_struct_find_value(&env, i1, "aas", &valueP);
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+            
+    /* "read" interface */
+            
+    xmlrpc_struct_read_value(&env, structP, "aas", &valueP);
+    TEST_NO_FAULT(&env);
+    TEST(valueP == i1);
+    xmlrpc_DECREF(valueP);
+            
+    xmlrpc_struct_read_value(&env, structP, "doesn't_exist", &valueP);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+            
+    xmlrpc_struct_read_value_v(&env, structP, aasStringP, &valueP);
+    TEST_NO_FAULT(&env);
+    TEST(valueP == i1);
+    xmlrpc_DECREF(valueP);
+            
+    xmlrpc_struct_read_value_v(&env, structP, bogusKeyStringP, &valueP);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+    xmlrpc_struct_read_value(&env, i1, "aas", &valueP);
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+            
+    /* obsolete "get" interface.  Note that it does not update the
+       reference count of the xmlrpc_value it returns.
+    */
+            
+    valueP = xmlrpc_struct_get_value(&env, structP, "aas");
+    TEST_NO_FAULT(&env);
+    TEST(valueP == i1);
+
+    valueP = xmlrpc_struct_get_value(&env, structP, "doesn't_exist");
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+    valueP = xmlrpc_struct_get_value(&env, i1, "foo");
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+    valueP = xmlrpc_struct_get_value_n(&env, structP, weirdKey, weirdKeyLen);
+    TEST_NO_FAULT(&env);
+    TEST(valueP == i2);
+
+    /* Clean up */
+
+    xmlrpc_DECREF(aasStringP);
+    xmlrpc_DECREF(bogusKeyStringP);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+testStructReadout(xmlrpc_value * const structP,
+                  size_t         const expectedSize) {
+
+    xmlrpc_env env;
+    xmlrpc_value * keyP;
+    xmlrpc_value * valueP;
+
+    unsigned int index;
+
+    xmlrpc_env_init(&env);
+
+    for (index = 0; index < expectedSize; ++index) {
+        xmlrpc_struct_read_member(&env, structP, index, &keyP, &valueP);
+        TEST_NO_FAULT(&env);
+        xmlrpc_DECREF(keyP);
+        xmlrpc_DECREF(valueP);
+    }
+
+    xmlrpc_struct_read_member(&env, structP, expectedSize, &keyP, &valueP);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    xmlrpc_env_clean(&env);
+    xmlrpc_env_init(&env);
+
+    for (index = 0; index < expectedSize; ++index) {
+        xmlrpc_struct_get_key_and_value(&env, structP, index, &keyP, &valueP);
+        TEST_NO_FAULT(&env);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+test_struct (void) {
+
+    xmlrpc_env env;
+    xmlrpc_value *s, *i, *i1, *i2, *i3, *key, *value;
+    size_t size;
+    int present;
+    xmlrpc_int32 ival;
+    xmlrpc_bool bval;
+    char *sval;
+    char const weirdKey[] = {'f', 'o', 'o', '\0', 'b', 'a', 'r'};
+
+    xmlrpc_env_init(&env);
+
+    /* Create a struct. */
+    s = xmlrpc_struct_new(&env);
+    TEST_NO_FAULT(&env);
+    TEST(s != NULL);
+    TEST(XMLRPC_TYPE_STRUCT == xmlrpc_value_type(s));
+    size = xmlrpc_struct_size(&env, s);
+    TEST_NO_FAULT(&env);
+    TEST(size == 0);
+
+    /* Create some elements to insert into our struct. */
+    i1 = xmlrpc_build_value(&env, "s", "Item #1");
+    TEST_NO_FAULT(&env);
+    i2 = xmlrpc_build_value(&env, "s", "Item #2");
+    TEST_NO_FAULT(&env);
+    i3 = xmlrpc_build_value(&env, "s", "Item #3");
+    TEST_NO_FAULT(&env);
+
+    /* Insert a single item. */
+    xmlrpc_struct_set_value(&env, s, "foo", i1);
+    TEST_NO_FAULT(&env);
+    size = xmlrpc_struct_size(&env, s);
+    TEST_NO_FAULT(&env);
+    TEST(size == 1);
+
+    /* Insert two more items with conflicting hash codes. (We assume that
+    ** nobody has changed the hash function.) */
+    xmlrpc_struct_set_value(&env, s, "bar", i2);
+    TEST_NO_FAULT(&env);
+    xmlrpc_struct_set_value(&env, s, "aas", i3);
+    TEST_NO_FAULT(&env);
+    size = xmlrpc_struct_size(&env, s);
+    TEST_NO_FAULT(&env);
+    TEST(size == 3);
+
+    /* Replace an existing element with a different element. */
+    xmlrpc_struct_set_value(&env, s, "aas", i1);
+    TEST_NO_FAULT(&env);
+    size = xmlrpc_struct_size(&env, s);
+    TEST_NO_FAULT(&env);
+    TEST(size == 3);
+
+    /* Insert an item with a NUL in the key */
+    xmlrpc_struct_set_value_n(&env, s, weirdKey, sizeof(weirdKey), i2);
+    TEST_NO_FAULT(&env);
+    size = xmlrpc_struct_size(&env, s);
+    TEST_NO_FAULT(&env);
+    TEST(size == 4);
+
+    test_struct_get_element(s, i1, i2, weirdKey, sizeof(weirdKey));
+
+    /* Replace an existing element with the same element (tricky). */
+    xmlrpc_struct_set_value(&env, s, "aas", i1);
+    TEST_NO_FAULT(&env);
+    size = xmlrpc_struct_size(&env, s);
+    TEST_NO_FAULT(&env);
+    TEST(size == 4);
+    i = xmlrpc_struct_get_value(&env, s, "aas");
+    TEST_NO_FAULT(&env);
+    TEST(i == i1);
+
+    /* Test for the presence and absence of elements. */
+    present = xmlrpc_struct_has_key(&env, s, "aas");
+    TEST_NO_FAULT(&env);
+    TEST(present);
+    present = xmlrpc_struct_has_key(&env, s, "bogus");
+    TEST_NO_FAULT(&env);
+    TEST(!present);
+
+    /* Make sure our typechecks work correctly. */
+    xmlrpc_struct_size(&env, i1);
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+    xmlrpc_struct_has_key(&env, i1, "foo");
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+    xmlrpc_struct_set_value(&env, i1, "foo", i2);
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+    xmlrpc_struct_set_value_v(&env, s, s, i2);
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+    /* Test cleanup code (w/memprof). */
+    xmlrpc_DECREF(s);
+
+    /* Build a struct using our automagic struct builder. */
+    s = xmlrpc_build_value(&env, "{s:s,s:i,s:b}",
+                           "foo", "Hello!",
+                           "bar", (xmlrpc_int32) 1,
+                           "baz", (xmlrpc_bool) 0);
+    TEST_NO_FAULT(&env);
+    TEST(s != NULL);
+    TEST(XMLRPC_TYPE_STRUCT == xmlrpc_value_type(s));
+    size = xmlrpc_struct_size(&env, s);
+    TEST_NO_FAULT(&env);
+    TEST(size == 3);
+    present = xmlrpc_struct_has_key(&env, s, "foo");
+    TEST_NO_FAULT(&env);
+    TEST(present);
+    present = xmlrpc_struct_has_key(&env, s, "bar");
+    TEST_NO_FAULT(&env);
+    TEST(present);
+    present = xmlrpc_struct_has_key(&env, s, "baz");
+    TEST_NO_FAULT(&env);
+    TEST(present);
+    i = xmlrpc_struct_get_value(&env, s, "baz");
+    TEST_NO_FAULT(&env);
+    xmlrpc_decompose_value(&env, i, "b", &bval);
+    TEST_NO_FAULT(&env);
+    TEST(!bval);
+
+    testStructReadout(s, 3);
+
+    /* Test our automagic struct parser. */
+    xmlrpc_decompose_value(&env, s, "{s:b,s:s,s:i,*}",
+                           "baz", &bval,
+                           "foo", &sval,
+                           "bar", &ival);
+    TEST_NO_FAULT(&env);
+    TEST(ival == 1);
+    TEST(!bval);
+    TEST(strcmp(sval, "Hello!") == 0);
+    free(sval);
+
+    /* Test automagic struct parser with value of wrong type. */
+    xmlrpc_decompose_value(&env, s, "{s:b,s:i,*}",
+                           "baz", &bval,
+                           "foo", &sval);
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+
+    /* Test automagic struct parser with bad key. */
+    xmlrpc_decompose_value(&env, s, "{s:b,s:i,*}",
+                           "baz", &bval,
+                           "nosuch", &sval);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+
+    /* Test type check. */
+    xmlrpc_struct_get_key_and_value(&env, i1, 0, &key, &value);
+    TEST_FAULT(&env, XMLRPC_TYPE_ERROR);
+    TEST(key == NULL && value == NULL);
+    
+    /* Test bounds checks. */
+    xmlrpc_struct_get_key_and_value(&env, s, -1, &key, &value);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    TEST(key == NULL && value == NULL);
+
+    xmlrpc_struct_get_key_and_value(&env, s, 3, &key, &value);
+    TEST_FAULT(&env, XMLRPC_INDEX_ERROR);
+    TEST(key == NULL && value == NULL);
+    
+    /* Test cleanup code (w/memprof). */
+    xmlrpc_DECREF(s);
+
+    xmlrpc_DECREF(i1);
+    xmlrpc_DECREF(i2);
+    xmlrpc_DECREF(i3);
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void 
+test_value(void) {
+
+    printf("Running value tests.");
+
+    test_value_alloc_dealloc();
+    test_value_integer();
+    test_value_bool();
+    test_value_double();
+    test_value_datetime();
+    test_value_string_no_null();
+    test_value_string_null();
+    test_value_string_wide();
+    test_value_base64();
+    test_value_array();
+    test_value_array2();
+    test_value_array_nil();
+    test_value_value();
+    test_value_AS();
+    test_value_AS_typecheck();
+    test_value_cptr();
+    test_value_nil();
+    test_value_type_mismatch();
+    test_value_invalid_type();
+    test_value_missing_array_delim();
+    test_value_missing_struct_delim();
+    test_value_invalid_struct();
+    test_value_parse_value();
+    test_struct();
+
+    printf("\n");
+    printf("Value tests done.\n");
+}
diff --git a/src/test/value.h b/src/test/value.h
new file mode 100644 (file)
index 0000000..2789def
--- /dev/null
@@ -0,0 +1,2 @@
+void 
+test_value(void);
diff --git a/src/test/xml_data.c b/src/test/xml_data.c
new file mode 100644 (file)
index 0000000..75cacf6
--- /dev/null
@@ -0,0 +1,196 @@
+#include <stddef.h>
+
+#include "xml_data.h"
+
+#define RAW_STRING_DATA \
+    "<value><array><data>\r\n" \
+    "<value><i4>2147483647</i4></value>\r\n" \
+    "<value><i4>-2147483648</i4></value>\r\n" \
+    "<value><boolean>0</boolean></value>\r\n" \
+    "<value><boolean>1</boolean></value>\r\n" \
+    "<value><string>Hello, world! &lt;&amp;&gt;</string></value>\r\n" \
+    "<value><base64>\r\n" \
+    "YmFzZTY0IGRhdGE=\r\n" \
+    "</base64></value>\r\n" \
+    "<value>" \
+      "<dateTime.iso8601>19980717T14:08:55</dateTime.iso8601>" \
+      "</value>\r\n" \
+    "<value><array><data>\r\n" \
+    "</data></array></value>\r\n" \
+    "</data></array></value>"
+    
+char const serialized_data[] = RAW_STRING_DATA;
+
+char const serialized_call[] =
+    XML_PROLOGUE
+    "<methodCall>\r\n"
+    "<methodName>gloom&amp;doom</methodName>\r\n"
+    "<params>\r\n"
+    "<param><value><i4>10</i4></value></param>\r\n"
+    "<param><value><i4>20</i4></value></param>\r\n"
+    "</params>\r\n"
+    "</methodCall>\r\n";
+
+char const serialized_fault[] =
+    XML_PROLOGUE
+    "<methodResponse>\r\n"
+    "<fault>\r\n"
+    "<value><struct>\r\n"
+    "<member><name>faultCode</name>\r\n"
+    "<value><i4>6</i4></value></member>\r\n"
+    "<member><name>faultString</name>\r\n"
+    "<value><string>A fault occurred</string></value></member>\r\n"
+    "</struct></value>\r\n"
+    "</fault>\r\n"
+    "</methodResponse>\r\n";
+
+char const expat_data[] = XML_PROLOGUE RAW_STRING_DATA "\r\n";
+char const expat_error_data[] =
+    XML_PROLOGUE \
+    "<foo><bar>abc</bar><baz></baz>\r\n";
+    /* Invalid because there's no closing </foo> */
+
+
+char const good_response_xml[] = 
+    XML_PROLOGUE 
+    "<methodResponse><params><param>\r\n" 
+    "<value><array><data>\r\n" 
+    RAW_STRING_DATA "\r\n" 
+    "<value><int>1</int></value>\r\n" 
+    "<value><double>-1.0</double></value>\r\n" 
+    "<value><double>0.0</double></value>\r\n" 
+    "<value><double>1.0</double></value>\r\n" 
+    "<value><struct>\r\n" 
+    "<member><name>ten &lt;&amp;&gt;</name>\r\n" 
+    "<value><i4>10</i4></value></member>\r\n" 
+    "<member><name>twenty</name>\r\n" 
+    "<value><i4>20</i4></value></member>\r\n" 
+    "</struct></value>\r\n" 
+    "<value>Untagged string</value>\r\n" 
+    "</data></array></value>\r\n" 
+    "</param></params></methodResponse>\r\n";
+
+#define VALUE_HEADER \
+    XML_PROLOGUE"<methodResponse><params><param><value>\r\n"
+#define VALUE_FOOTER \
+    "</value></param></params></methodResponse>\r\n"
+
+#define MEMBER_HEADER \
+    VALUE_HEADER"<struct><member>"
+#define MEMBER_FOOTER \
+    "</member></struct>"VALUE_FOOTER
+#define ARBITRARY_VALUE \
+    "<value><i4>0</i4></value>"
+
+char const unparseable_value[] = VALUE_HEADER"<i4>"VALUE_FOOTER;
+
+const char * bad_values[] = {
+    VALUE_HEADER"<i4>0</i4><i4>0</i4>"VALUE_FOOTER,
+    VALUE_HEADER"<foo></foo>"VALUE_FOOTER,
+    VALUE_HEADER"<i4><i4>4</i4></i4>"VALUE_FOOTER,
+    VALUE_HEADER"<i4>2147483648</i4>"VALUE_FOOTER,
+    VALUE_HEADER"<i4>-2147483649</i4>"VALUE_FOOTER,
+    VALUE_HEADER"<i4> 0</i4>"VALUE_FOOTER,
+    VALUE_HEADER"<i4>0 </i4>"VALUE_FOOTER,
+    VALUE_HEADER"<boolean>2</boolean>"VALUE_FOOTER,
+    VALUE_HEADER"<boolean>-1</boolean>"VALUE_FOOTER,
+    VALUE_HEADER"<double> 0.0</double>"VALUE_FOOTER,
+    VALUE_HEADER"<double>0.0 </double>"VALUE_FOOTER,
+    VALUE_HEADER"<array></array>"VALUE_FOOTER,
+    VALUE_HEADER"<array><data></data><data></data></array>"VALUE_FOOTER,
+    VALUE_HEADER"<array><data></data><data></data></array>"VALUE_FOOTER,
+    VALUE_HEADER"<array><data><foo></foo></data></array>"VALUE_FOOTER,
+    VALUE_HEADER"<struct><foo></foo></struct>"VALUE_FOOTER,
+    MEMBER_HEADER MEMBER_FOOTER,
+    MEMBER_HEADER"<name>a</name>"MEMBER_FOOTER,
+    MEMBER_HEADER"<name>a</name>"ARBITRARY_VALUE"<f></f>"MEMBER_FOOTER,
+    MEMBER_HEADER"<foo></foo>"ARBITRARY_VALUE MEMBER_FOOTER,
+    MEMBER_HEADER"<name>a</name><foo></foo>"MEMBER_FOOTER,
+    MEMBER_HEADER"<name><foo></foo></name>"ARBITRARY_VALUE MEMBER_FOOTER,
+    NULL
+};
+
+#define RESPONSE_HEADER \
+    XML_PROLOGUE"<methodResponse>\r\n"
+#define RESPONSE_FOOTER \
+    "</methodResponse>\r\n"
+
+#define PARAMS_RESP_HEADER \
+    RESPONSE_HEADER"<params>"
+#define PARAMS_RESP_FOOTER \
+    "</params>"RESPONSE_FOOTER
+
+#define FAULT_HEADER \
+    RESPONSE_HEADER"<fault>"
+#define FAULT_FOOTER \
+    "</fault>"RESPONSE_FOOTER
+
+#define FAULT_STRUCT_HEADER \
+    FAULT_HEADER"<value><struct>"
+#define FAULT_STRUCT_FOOTER \
+    "</struct></value>"FAULT_FOOTER
+
+const char * bad_responses[] = {
+    XML_PROLOGUE"<foo></foo>\r\n",
+    RESPONSE_HEADER RESPONSE_FOOTER,
+    RESPONSE_HEADER"<params></params><params></params>"RESPONSE_FOOTER,
+    RESPONSE_HEADER"<foo></foo>"RESPONSE_FOOTER,
+
+    /* Make sure we insist on only one parameter in a response. */
+    PARAMS_RESP_HEADER PARAMS_RESP_FOOTER,
+    PARAMS_RESP_HEADER
+    "<param><i4>0</i4></param>"
+    "<param><i4>0</i4></param>"
+    PARAMS_RESP_FOOTER,
+
+    /* Test other sorts of bad parameters. */
+    PARAMS_RESP_HEADER"<foo></foo>"PARAMS_RESP_FOOTER,
+    PARAMS_RESP_HEADER"<param></param>"PARAMS_RESP_FOOTER,
+    PARAMS_RESP_HEADER"<param><foo></foo></param>"PARAMS_RESP_FOOTER,
+    PARAMS_RESP_HEADER
+    "<param>"ARBITRARY_VALUE ARBITRARY_VALUE"</param>"
+    PARAMS_RESP_FOOTER,
+    
+    /* Basic fault tests. */
+    FAULT_HEADER FAULT_FOOTER,
+    FAULT_HEADER"<foo></foo>"FAULT_FOOTER,
+    FAULT_HEADER"<value></value><value></value>"FAULT_FOOTER,
+    FAULT_HEADER"<value><i4>1</i4></value>"FAULT_FOOTER,
+
+    /* Make sure we insist on the proper members within the fault struct. */
+    FAULT_STRUCT_HEADER
+    "<member><name>faultString</name>"
+    "<value><string>foo</string></value></member>"
+    FAULT_STRUCT_FOOTER,
+    FAULT_STRUCT_HEADER
+    "<member><name>faultCode</name>"
+    "<value><i4>0</i4></value></member>"
+    FAULT_STRUCT_FOOTER,
+    FAULT_STRUCT_HEADER
+    "<member><name>faultCode</name>"
+    "<value><i4>0</i4></value></member>"
+    "<member><name>faultString</name>"
+    "<value><i4>0</i4></value></member>"
+    FAULT_STRUCT_FOOTER,
+    FAULT_STRUCT_HEADER
+    "<member><name>faultCode</name>"
+    "<value><string>0</string></value></member>"
+    "<member><name>faultString</name>"
+    "<value><string>foo</string></value></member>"
+    FAULT_STRUCT_FOOTER,
+    NULL};
+
+#define CALL_HEADER \
+    XML_PROLOGUE"<methodCall>\r\n"
+#define CALL_FOOTER \
+    "</methodCall>\r\n"
+
+const char * bad_calls[] = {
+    XML_PROLOGUE"<foo></foo>\r\n",
+    CALL_HEADER CALL_FOOTER,
+    CALL_HEADER"<methodName>m</methodName><foo></foo>"CALL_FOOTER, 
+    CALL_HEADER"<foo></foo><params></params>"CALL_FOOTER, 
+    CALL_HEADER"<methodName><f></f></methodName><params></params>"CALL_FOOTER, 
+    NULL};
+
+
diff --git a/src/test/xml_data.h b/src/test/xml_data.h
new file mode 100644 (file)
index 0000000..4b34238
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef XML_DATA_H_INCLUDED
+#define XML_DATA_H_INCLUDED
+
+#define XML_PROLOGUE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+
+extern char const serialized_data[];
+
+extern char const serialized_call[];
+
+extern char const serialized_fault[];
+
+extern char const expat_data[];
+extern char const expat_error_data[];
+
+extern char const good_response_xml[];
+
+extern char const unparseable_value[];
+
+extern const char *(bad_values[]);
+
+extern const char *(bad_responses[]);
+
+extern const char *(bad_calls[]);
+
+#endif
diff --git a/src/trace.c b/src/trace.c
new file mode 100644 (file)
index 0000000..1e56acb
--- /dev/null
@@ -0,0 +1,62 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+
+
+static size_t
+nextLineSize(const char * const string,
+             size_t       const startPos,
+             size_t       const stringSize) {
+/*----------------------------------------------------------------------------
+   Return the length of the line that starts at offset 'startPos' in the
+   string 'string', which is 'stringSize' characters long.
+
+   'string' in not NUL-terminated.
+   
+   A line begins at beginning of string or after a newline character and
+   runs through the next newline character or end of string.  The line
+   includes the newline character at the end, if any.
+-----------------------------------------------------------------------------*/
+    size_t i;
+
+    for (i = startPos; i < stringSize && string[i] != '\n'; ++i);
+
+    if (i < stringSize)
+        ++i;  /* Include the newline */
+
+    return i - startPos;
+}
+
+
+
+void
+xmlrpc_traceXml(const char * const label, 
+                char         const xml[],
+                unsigned int const xmlLength) {
+
+    if (getenv("XMLRPC_TRACE_XML")) {
+        size_t cursor;  /* Index into xml[] */
+
+        fprintf(stderr, "%s:\n\n", label);
+
+        for (cursor = 0; cursor < xmlLength; ) {
+            /* Print one line of XML */
+
+            size_t const lineSize = nextLineSize(xml, cursor, xmlLength);
+            const char * const xmlPrintableLine =
+                xmlrpc_makePrintable_lp(&xml[cursor], lineSize);
+
+            fprintf(stderr, "%s\n", xmlPrintableLine);
+
+            cursor += lineSize;
+
+            xmlrpc_strfree(xmlPrintableLine);
+        }
+        fprintf(stderr, "\n");
+    }
+}
+
diff --git a/src/xmlrpc_array.c b/src/xmlrpc_array.c
new file mode 100644 (file)
index 0000000..9cba28c
--- /dev/null
@@ -0,0 +1,255 @@
+/* Copyright information is at the end of the file */
+
+/*=========================================================================
+**  XML-RPC Array Functions
+**=========================================================================
+*/
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "xmlrpc-c/util.h"
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+
+
+
+void
+xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP) {
+
+    if (arrayP == NULL)
+        abort();
+    else if (arrayP->_type != XMLRPC_TYPE_ARRAY)
+        abort();
+    else {
+        unsigned int const arraySize =
+            XMLRPC_MEMBLOCK_SIZE(xmlrpc_value*, &arrayP->_block);
+        xmlrpc_value ** const contents = 
+            XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block);
+        
+        if (contents == NULL)
+            abort();
+        else {
+            unsigned int index;
+            
+            for (index = 0; index < arraySize; ++index) {
+                xmlrpc_value * const itemP = contents[index];
+                if (itemP == NULL)
+                    abort();
+                else if (itemP->_refcount < 1)
+                    abort();
+            }
+        }
+    }
+}
+
+
+
+void
+xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP) {
+/*----------------------------------------------------------------------------
+   Dispose of the contents of an array (but not the array value itself).
+   The value is not valid after this.
+-----------------------------------------------------------------------------*/
+    unsigned int const arraySize =
+        XMLRPC_MEMBLOCK_SIZE(xmlrpc_value*, &arrayP->_block);
+    xmlrpc_value ** const contents = 
+        XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block);
+
+    unsigned int index;
+    
+    XMLRPC_ASSERT_ARRAY_OK(arrayP);
+
+    /* Release our reference to each item in the array */
+    for (index = 0; index < arraySize; ++index) {
+        xmlrpc_value * const itemP = contents[index];
+        xmlrpc_DECREF(itemP);
+    }
+    XMLRPC_MEMBLOCK_CLEAN(xmlrpc_value *, &arrayP->_block);
+}
+
+
+
+int 
+xmlrpc_array_size(xmlrpc_env *         const env, 
+                  const xmlrpc_value * const array) {
+
+    int retval;
+
+    /* Suppress a compiler warning about uninitialized variables. */
+    retval = 0;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_VALUE_OK(array);
+    XMLRPC_TYPE_CHECK(env, array, XMLRPC_TYPE_ARRAY);
+
+    retval = XMLRPC_TYPED_MEM_BLOCK_SIZE(xmlrpc_value*, &array->_block);
+
+                  cleanup:
+    if (env->fault_occurred)
+        return -1;
+    else
+        return retval;
+}
+
+
+
+void 
+xmlrpc_array_append_item(xmlrpc_env *   const envP,
+                         xmlrpc_value * const arrayP,
+                         xmlrpc_value * const valueP) {
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(arrayP);
+    
+    if (xmlrpc_value_type(arrayP) != XMLRPC_TYPE_ARRAY)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TYPE_ERROR, "Value is not an array");
+    else {
+        size_t const size = 
+            XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block);
+
+        XMLRPC_MEMBLOCK_RESIZE(xmlrpc_value *, envP, &arrayP->_block, size+1);
+
+        if (!envP->fault_occurred) {
+            xmlrpc_value ** const contents =
+                XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block);
+            xmlrpc_INCREF(valueP);
+            contents[size] = valueP;
+        }
+    }
+}
+
+
+
+void
+xmlrpc_array_read_item(xmlrpc_env *         const envP,
+                       const xmlrpc_value * const arrayP,
+                       unsigned int         const index,
+                       xmlrpc_value **      const valuePP) {
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(arrayP);
+    XMLRPC_ASSERT_PTR_OK(valuePP);
+
+    if (arrayP->_type != XMLRPC_TYPE_ARRAY)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TYPE_ERROR, "Attempt to read array item from "
+            "a value that is not an array");
+    else {
+        xmlrpc_value ** const contents = 
+            XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value *, &arrayP->_block);
+        size_t const size = 
+            XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block);
+
+        if (index >= size)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INDEX_ERROR, "Array index %u is beyond end "
+                "of %u-item array", index, (unsigned int)size);
+        else {
+            *valuePP = contents[index];
+            xmlrpc_INCREF(*valuePP);
+        }
+    }
+}
+
+
+
+xmlrpc_value * 
+xmlrpc_array_get_item(xmlrpc_env *         const envP,
+                      const xmlrpc_value * const arrayP,
+                      int                  const indexArg) {
+
+    /* We must maintain the historical thread-safeness of
+       xmlrpc_array_get_item().  That means we can't call
+       xmlrpc_read_array(), because it modifies the reference count
+       of its arguments, thus is not thread-safe.
+
+       The Xmlrpc-c method registry is an example of an application that
+       relies on thread-safeness of xmlrpc_array_get_item() -- it uses
+       xmlrpc_value's to represent the registry, and multiple server
+       threads read the registry simultaneously.
+    */
+
+    xmlrpc_value * valueP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(arrayP);
+
+    valueP = NULL;
+
+    if (indexArg < 0)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INDEX_ERROR, "Index %d is negative.", indexArg);
+    else {
+        unsigned int const index = indexArg;
+
+        if (arrayP->_type != XMLRPC_TYPE_ARRAY)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_TYPE_ERROR, "Attempt to read array item from "
+                "a value that is not an array");
+        else {
+            xmlrpc_value ** const contents = 
+                XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value *, &arrayP->_block);
+            size_t const size = 
+                XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block);
+
+            if (index >= size)
+                xmlrpc_env_set_fault_formatted(
+                    envP, XMLRPC_INDEX_ERROR, "Array index %u is beyond end "
+                    "of %u-item array", index, (unsigned int)size);
+            else
+                valueP = contents[index];
+        }
+    }
+    return valueP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_array_new(xmlrpc_env * const envP) {
+/*----------------------------------------------------------------------------
+   Create an empty array xmlrpc_value.
+-----------------------------------------------------------------------------*/
+    xmlrpc_value * arrayP;
+
+    xmlrpc_createXmlrpcValue(envP, &arrayP);
+    if (!envP->fault_occurred) {
+        arrayP->_type = XMLRPC_TYPE_ARRAY;
+        XMLRPC_MEMBLOCK_INIT(xmlrpc_value*, envP, &arrayP->_block, 0);
+        if (envP->fault_occurred)
+            free(arrayP);
+    }
+    return arrayP;
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2001 by Eric Kidd. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/src/xmlrpc_authcookie.c b/src/xmlrpc_authcookie.c
new file mode 100644 (file)
index 0000000..b29cc92
--- /dev/null
@@ -0,0 +1,85 @@
+/* Copyright (C) 2002 by jeff@ourexchange.net. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mallocvar.h"
+#include "xmlrpc-c/base.h"
+
+/*****************************************************************************
+  I don't see how these were expected to be used.  And I probably
+  broke it somehow at some point by removing code from somewhere else.
+  But I doubt that, whatever it's supposed to do, environment
+  variables are the right tool.
+
+  Note that on a platform that doesn't have SETENV,
+  xmlrpc_authcookie_set() is just a no-op.
+
+  -Bryan 2005.06.10
+****************************************************************************/
+
+void 
+xmlrpc_authcookie_set(xmlrpc_env * const envP, 
+                      const char * const username, 
+                      const char * const password) {
+
+    char * unencoded;
+    xmlrpc_mem_block * token;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(username);
+    XMLRPC_ASSERT_PTR_OK(password);
+
+    /* Create unencoded string/hash. */
+
+    MALLOCARRAY(unencoded,(strlen(username) + strlen(password) + 1 + 1));
+    sprintf(unencoded, "%s:%s", username, password);
+    
+    /* Create encoded string. */
+    token = xmlrpc_base64_encode_without_newlines(
+        envP, (unsigned char *)unencoded, strlen(unencoded));
+    if (!envP->fault_occurred) {
+        /* Set HTTP_COOKIE_AUTH to the character representation of the
+           encoded string.
+        */
+#ifdef HAVE_SETENV
+        setenv("HTTP_COOKIE_AUTH", 
+               XMLRPC_MEMBLOCK_CONTENTS(char, token),
+               1);
+#endif
+        xmlrpc_mem_block_free(token);
+    }
+    free(unencoded);
+}
+
+
+
+char *xmlrpc_authcookie ( void ) {
+    return getenv("HTTP_COOKIE_AUTH");
+}
diff --git a/src/xmlrpc_base64.c b/src/xmlrpc_base64.c
new file mode 100644 (file)
index 0000000..2f54377
--- /dev/null
@@ -0,0 +1,266 @@
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+** There is more copyright information in the bottom half of this file. 
+** Please see it for more details. */
+
+
+/*=========================================================================
+**  XML-RPC Base64 Utilities
+**=========================================================================
+**  This code was swiped from Jack Jansen's code in Python 1.5.2 and
+**  modified to work with our data types.
+*/
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+
+#define CRLF    "\015\012"
+#define CR      '\015'
+#define LF      '\012'
+
+
+/***********************************************************
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI or Corporation for National Research Initiatives or
+CNRI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+While CWI is the initial source for this software, a modified version
+is made available by the Corporation for National Research Initiatives
+(CNRI) at the Internet address ftp://ftp.python.org.
+
+STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
+CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+static char table_a2b_base64[] = {
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+    52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, /* Note PAD->0 */
+    -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
+    15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+    -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+    41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+};
+
+#define BASE64_PAD '='
+#define BASE64_MAXBIN 57    /* Max binary chunk size (76 char line) */
+#define BASE64_LINE_SZ 128      /* Buffer size for a single line. */    
+
+static unsigned char table_b2a_base64[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static xmlrpc_mem_block *
+xmlrpc_base64_encode_internal (xmlrpc_env *env,
+                               unsigned char *bin_data,
+                               size_t bin_len,
+                               int want_newlines)
+{
+    size_t chunk_start, chunk_left;
+    unsigned char *ascii_data;
+    int leftbits;
+    unsigned char this_ch;
+    unsigned int leftchar;
+    xmlrpc_mem_block *output;
+    unsigned char line_buffer[BASE64_LINE_SZ];
+
+    /* Create a block to hold our lines when we finish them. */
+    output = xmlrpc_mem_block_new(env, 0);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Deal with empty data blocks gracefully. Yuck. */
+    if (bin_len == 0) {
+        if (want_newlines)
+            XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, CRLF, 2);
+        goto cleanup;
+    }
+
+    /* Process our binary data in line-sized chunks. */
+    for (chunk_start=0; chunk_start < bin_len; chunk_start += BASE64_MAXBIN) {
+
+        /* Set up our per-line state. */
+        ascii_data = &line_buffer[0];
+        chunk_left = bin_len - chunk_start;
+        if (chunk_left > BASE64_MAXBIN)
+            chunk_left = BASE64_MAXBIN;
+        leftbits = 0;
+        leftchar = 0;
+
+        for(; chunk_left > 0; chunk_left--, bin_data++) {
+            /* Shift the data into our buffer */
+            leftchar = (leftchar << 8) | *bin_data;
+            leftbits += 8;
+
+            /* See if there are 6-bit groups ready */
+            while (leftbits >= 6) {
+                this_ch = (leftchar >> (leftbits-6)) & 0x3f;
+                leftbits -= 6;
+                *ascii_data++ = table_b2a_base64[this_ch];
+            }
+        }
+        if (leftbits == 2) {
+            *ascii_data++ = table_b2a_base64[(leftchar&3) << 4];
+            *ascii_data++ = BASE64_PAD;
+            *ascii_data++ = BASE64_PAD;
+        } else if (leftbits == 4) {
+            *ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2];
+            *ascii_data++ = BASE64_PAD;
+        } 
+
+        /* Append a courtesy CRLF. */
+        if (want_newlines) {
+            *ascii_data++ = CR;
+            *ascii_data++ = LF;
+        }
+    
+        /* Save our line. */
+        XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, line_buffer,
+                                      ascii_data - &line_buffer[0]);
+        XMLRPC_FAIL_IF_FAULT(env);
+    }
+
+ cleanup:
+    if (env->fault_occurred) {
+        if (output)
+            xmlrpc_mem_block_free(output);
+        return NULL;
+    }
+    return output;
+}
+
+
+xmlrpc_mem_block *
+xmlrpc_base64_encode (xmlrpc_env *env, unsigned char *bin_data, size_t bin_len)
+{
+    return xmlrpc_base64_encode_internal(env, bin_data, bin_len, 1);
+}
+
+
+xmlrpc_mem_block *
+xmlrpc_base64_encode_without_newlines (xmlrpc_env *env,
+                                       unsigned char *bin_data,
+                                       size_t bin_len)
+{
+    return xmlrpc_base64_encode_internal(env, bin_data, bin_len, 0);
+}
+
+
+xmlrpc_mem_block *
+xmlrpc_base64_decode (xmlrpc_env * const env,
+                      const char * const ascii_data,
+                      size_t       const ascii_len) {
+
+    unsigned char *bin_data;
+    int leftbits;
+    unsigned char this_ch;
+    unsigned int leftchar;
+    size_t npad;
+    size_t bin_len, buffer_size;
+    xmlrpc_mem_block *output;
+    const char * next_char;
+    size_t remaining_len;
+
+    /* Create a block to hold our chunks when we finish them.
+    ** We overestimate the size now, and fix it later. */
+    buffer_size = ((ascii_len+3)/4)*3;
+    output = xmlrpc_mem_block_new(env, buffer_size);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Set up our decoder state. */
+    leftbits = 0;
+    leftchar = 0;
+    npad = 0;
+    bin_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(unsigned char, output);
+    bin_len = 0;
+
+    for (remaining_len = ascii_len, next_char = ascii_data;
+         remaining_len > 0; 
+         --remaining_len, ++next_char) {
+
+        /* Skip some punctuation. */
+        this_ch = (*next_char & 0x7f);
+        if ( this_ch == '\r' || this_ch == '\n' || this_ch == ' ' )
+            continue;
+        if ( this_ch == BASE64_PAD )
+            npad++;
+        this_ch = table_a2b_base64[(*next_char) & 0x7f];
+
+        /* XXX - We just throw away invalid characters. Is this right? */
+        if ( this_ch == (unsigned char) -1 ) continue;
+
+        /* Shift it in on the low end, and see if there's
+        ** a byte ready for output. */
+        leftchar = (leftchar << 6) | (this_ch);
+        leftbits += 6;
+        if ( leftbits >= 8 ) {
+            leftbits -= 8;
+            XMLRPC_ASSERT(bin_len < buffer_size);
+            *bin_data++ = (leftchar >> leftbits) & 0xFF;
+            leftchar &= ((1 << leftbits) - 1);
+            bin_len++;
+        }
+    }
+
+    /* Check that no bits are left. */
+    if ( leftbits )
+        XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR, "Incorrect Base64 padding");
+
+    /* Check to make sure we have a sane amount of padding. */
+    if (npad > bin_len || npad > 2)
+        XMLRPC_FAIL(env, XMLRPC_PARSE_ERROR, "Malformed Base64 data");
+
+    /* Remove any padding and set the correct size. */
+    bin_len -= npad;
+    XMLRPC_TYPED_MEM_BLOCK_RESIZE(char, env, output, bin_len);
+    XMLRPC_ASSERT(!env->fault_occurred);
+
+                      cleanup:
+    if (env->fault_occurred) {
+        if (output)
+            xmlrpc_mem_block_free(output);
+        return NULL;
+    }
+    return output;
+}
diff --git a/src/xmlrpc_builddecomp.c b/src/xmlrpc_builddecomp.c
new file mode 100644 (file)
index 0000000..f0e58d7
--- /dev/null
@@ -0,0 +1,971 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "bool.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+
+/* Borrowed from Python 1.5.2.
+** MPW pushes 'extended' for float and double types with varargs */
+#ifdef MPW
+typedef extended va_double;
+#else
+typedef double va_double;
+#endif
+
+/* Borrowed from Python 1.5.2.
+** Python copies its va_list objects before using them in certain
+** tricky fashions. We don't why Python does this, but since we're
+** abusing our va_list objects in a similar fashion, we'll copy them
+** too. */
+#if VA_LIST_IS_ARRAY
+#define VA_LIST_COPY(dest,src) memcpy((dest), (src), sizeof(va_list))
+#else
+#define VA_LIST_COPY(dest,src) ((dest) = (src))
+#endif
+
+/*=========================================================================
+**  Creating XML-RPC values.
+**=========================================================================
+**  Build new XML-RPC values from a format string. This code is heavily
+**  inspired by Py_BuildValue from Python 1.5.2. In particular, our
+**  particular abuse of the va_list data type is copied from the equivalent
+**  Python code in modsupport.c. Since Python is portable, our code should
+**  (in theory) also be portable.
+*/
+
+
+static void
+getString(xmlrpc_env *    const envP,
+          const char **   const formatP,
+          va_list *       const args,
+          xmlrpc_value ** const valPP) {
+
+    const char * str;
+    unsigned int len;
+    
+    str = (const char*) va_arg(*args, char*);
+    if (**formatP == '#') {
+        (*formatP)++;
+        len = (size_t) va_arg(*args, size_t);
+    } else
+        len = strlen(str);
+
+    *valPP = xmlrpc_string_new_lp(envP, len, str);
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+static void
+mkWideString(xmlrpc_env *    const envP,
+             wchar_t *       const wcs,
+             size_t          const wcs_len,
+             xmlrpc_value ** const valPP) {
+
+    xmlrpc_value * valP;
+    char *contents;
+    wchar_t *wcs_contents;
+    int block_is_inited;
+    xmlrpc_mem_block *utf8_block;
+    char *utf8_contents;
+    size_t utf8_len;
+
+    /* Error-handling preconditions. */
+    valP = NULL;
+    utf8_block = NULL;
+    block_is_inited = 0;
+
+    /* Initialize our XML-RPC value. */
+    valP = (xmlrpc_value*) malloc(sizeof(xmlrpc_value));
+    XMLRPC_FAIL_IF_NULL(valP, envP, XMLRPC_INTERNAL_ERROR,
+                        "Could not allocate memory for wide string");
+    valP->_refcount = 1;
+    valP->_type = XMLRPC_TYPE_STRING;
+
+    /* More error-handling preconditions. */
+    valP->_wcs_block = NULL;
+
+    /* Build our wchar_t block first. */
+    valP->_wcs_block =
+        XMLRPC_TYPED_MEM_BLOCK_NEW(wchar_t, envP, wcs_len + 1);
+    XMLRPC_FAIL_IF_FAULT(envP);
+    wcs_contents =
+        XMLRPC_TYPED_MEM_BLOCK_CONTENTS(wchar_t, valP->_wcs_block);
+    memcpy(wcs_contents, wcs, wcs_len * sizeof(wchar_t));
+    wcs_contents[wcs_len] = '\0';
+    
+    /* Convert the wcs block to UTF-8. */
+    utf8_block = xmlrpc_wcs_to_utf8(envP, wcs_contents, wcs_len + 1);
+    XMLRPC_FAIL_IF_FAULT(envP);
+    utf8_contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, utf8_block);
+    utf8_len = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, utf8_block);
+
+    /* XXX - We need an extra memcopy to initialize _block. */
+    XMLRPC_TYPED_MEM_BLOCK_INIT(char, envP, &valP->_block, utf8_len);
+    XMLRPC_FAIL_IF_FAULT(envP);
+    block_is_inited = 1;
+    contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block);
+    memcpy(contents, utf8_contents, utf8_len);
+
+ cleanup:
+    if (utf8_block)
+        xmlrpc_mem_block_free(utf8_block);
+    if (envP->fault_occurred) {
+        if (valP) {
+            if (valP->_wcs_block)
+                xmlrpc_mem_block_free(valP->_wcs_block);
+            if (block_is_inited)
+                xmlrpc_mem_block_clean(&valP->_block);
+            free(valP);
+        }
+    }
+    *valPP = valP;
+}
+#endif /* HAVE_UNICODE_WCHAR */
+
+
+
+static void
+getWideString(xmlrpc_env *    const envP ATTR_UNUSED,
+              const char **   const formatP ATTR_UNUSED,
+              va_list *       const args ATTR_UNUSED,
+              xmlrpc_value ** const valPP ATTR_UNUSED) {
+
+#if HAVE_UNICODE_WCHAR
+    wchar_t *wcs;
+    size_t len;
+    
+    wcs = (wchar_t*) va_arg(*args, wchar_t*);
+    if (**formatP == '#') {
+        (*formatP)++;
+        len = (size_t) va_arg(*args, size_t);
+    } else
+        len = wcslen(wcs);
+
+    mkWideString(envP, wcs, len, valPP);
+
+#endif /* HAVE_UNICODE_WCHAR */
+}
+
+
+
+static void
+getBase64(xmlrpc_env *    const envP,
+          va_list *       const args,
+          xmlrpc_value ** const valPP) {
+
+    unsigned char * value;
+    size_t          length;
+    
+    value  = (unsigned char*) va_arg(*args, unsigned char*);
+    length = (size_t)         va_arg(*args, size_t);
+
+    *valPP = xmlrpc_base64_new(envP, length, value);
+}
+
+
+
+static void
+getValue(xmlrpc_env *    const envP, 
+         const char**    const format, 
+         va_list *             args,
+         xmlrpc_value ** const valPP);
+
+
+
+static void
+getArray(xmlrpc_env *    const envP,
+         const char **   const formatP,
+         char            const delimiter,
+         va_list *       const args,
+         xmlrpc_value ** const arrayPP) {
+
+    xmlrpc_value * arrayP;
+
+    arrayP = xmlrpc_array_new(envP);
+
+    /* Add items to the array until we hit our delimiter. */
+    
+    while (**formatP != delimiter && !envP->fault_occurred) {
+        
+        xmlrpc_value * itemP;
+        
+        if (**formatP == '\0')
+            xmlrpc_env_set_fault(
+                envP, XMLRPC_INTERNAL_ERROR,
+                "format string ended before closing ')'.");
+        else {
+            getValue(envP, formatP, args, &itemP);
+            if (!envP->fault_occurred) {
+                xmlrpc_array_append_item(envP, arrayP, itemP);
+                xmlrpc_DECREF(itemP);
+            }
+        }
+    }
+    if (envP->fault_occurred)
+        xmlrpc_DECREF(arrayP);
+
+    *arrayPP = arrayP;
+}
+
+
+
+static void
+getStructMember(xmlrpc_env *    const envP,
+                const char **   const formatP,
+                va_list *       const args,
+                xmlrpc_value ** const keyPP,
+                xmlrpc_value ** const valuePP) {
+
+
+    /* Get the key */
+    getValue(envP, formatP, args, keyPP);
+    if (!envP->fault_occurred) {
+        if (**formatP != ':')
+            xmlrpc_env_set_fault(
+                envP, XMLRPC_INTERNAL_ERROR,
+                "format string does not have ':' after a "
+                "structure member key.");
+        else {
+            /* Skip over colon that separates key from value */
+            (*formatP)++;
+            
+            /* Get the value */
+            getValue(envP, formatP, args, valuePP);
+        }
+        if (envP->fault_occurred)
+            xmlrpc_DECREF(*keyPP);
+    }
+}
+            
+            
+
+static void
+getStruct(xmlrpc_env *    const envP,
+          const char **   const formatP,
+          char            const delimiter,
+          va_list *       const args,
+          xmlrpc_value ** const structPP) {
+
+    xmlrpc_value * structP;
+
+    structP = xmlrpc_struct_new(envP);
+    if (!envP->fault_occurred) {
+        while (**formatP != delimiter && !envP->fault_occurred) {
+            xmlrpc_value * keyP;
+            xmlrpc_value * valueP;
+            
+            getStructMember(envP, formatP, args, &keyP, &valueP);
+            
+            if (!envP->fault_occurred) {
+                if (**formatP == ',')
+                    (*formatP)++;  /* Skip over the comma */
+                else if (**formatP == delimiter) {
+                    /* End of the line */
+                } else 
+                    xmlrpc_env_set_fault(
+                        envP, XMLRPC_INTERNAL_ERROR,
+                        "format string does not have ',' or ')' after "
+                        "a structure member");
+                
+                if (!envP->fault_occurred)
+                    /* Add the new member to the struct. */
+                    xmlrpc_struct_set_value_v(envP, structP, keyP, valueP);
+                
+                xmlrpc_DECREF(valueP);
+                xmlrpc_DECREF(keyP);
+            }
+        }
+        if (envP->fault_occurred)
+            xmlrpc_DECREF(structP);
+    }
+    *structPP = structP;
+}
+
+
+
+static void
+mkArrayFromVal(xmlrpc_env *    const envP, 
+               xmlrpc_value *  const value,
+               xmlrpc_value ** const valPP) {
+
+    if (xmlrpc_value_type(value) != XMLRPC_TYPE_ARRAY)
+        xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+                             "Array format ('A'), non-array xmlrpc_value");
+    else
+        xmlrpc_INCREF(value);
+
+    *valPP = value;
+}
+
+
+
+static void
+mkStructFromVal(xmlrpc_env *    const envP, 
+                xmlrpc_value *  const value,
+                xmlrpc_value ** const valPP) {
+
+    if (xmlrpc_value_type(value) != XMLRPC_TYPE_STRUCT)
+        xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+                             "Struct format ('S'), non-struct xmlrpc_value");
+    else
+        xmlrpc_INCREF(value);
+
+    *valPP = value;
+}
+
+
+
+static void
+getValue(xmlrpc_env *    const envP, 
+         const char**    const formatP,
+         va_list *       const args,
+         xmlrpc_value ** const valPP) {
+/*----------------------------------------------------------------------------
+   Get the next value from the list.  *formatP points to the specifier
+   for the next value in the format string (i.e. to the type code
+   character) and we move *formatP past the whole specifier for the
+   next value.  We read the required arguments from 'args'.  We return
+   the value as *valPP with a reference to it.
+
+   For example, if *formatP points to the "i" in the string "sis",
+   we read one argument from 'args' and return as *valP an integer whose
+   value is the argument we read.  We advance *formatP to point to the
+   last 's' and advance 'args' to point to the argument that belongs to
+   that 's'.
+-----------------------------------------------------------------------------*/
+    char const formatChar = *(*formatP)++;
+
+    switch (formatChar) {
+    case 'i':
+        *valPP = 
+            xmlrpc_int_new(envP, (xmlrpc_int32) va_arg(*args, xmlrpc_int32));
+        break;
+
+    case 'b':
+        *valPP = 
+            xmlrpc_bool_new(envP, (xmlrpc_bool) va_arg(*args, xmlrpc_bool));
+        break;
+
+    case 'd':
+        *valPP =
+            xmlrpc_double_new(envP, (double) va_arg(*args, va_double));
+        break;
+
+    case 's':
+        getString(envP, formatP, args, valPP);
+        break;
+
+    case 'w':
+        getWideString(envP, formatP, args, valPP);
+        break;
+
+    /* The code 't' is reserved for a better, time_t based
+       implementation of dateTime conversion.  
+    */
+    case '8':
+        *valPP = 
+            xmlrpc_datetime_new_str(envP, (char*) va_arg(*args, char*));
+        break;
+
+    case '6':
+        getBase64(envP, args, valPP);
+        break;
+
+    case 'n':
+        *valPP =
+            xmlrpc_nil_new(envP);
+        break;      
+
+    case 'p':
+        /* We might someday want to use the code 'p!' to read in a
+           cleanup function for this pointer. 
+        */
+        *valPP = 
+            xmlrpc_cptr_new(envP, (void*) va_arg(*args, void*));
+        break;      
+
+    case 'A':
+        mkArrayFromVal(envP, (xmlrpc_value*) va_arg(*args, xmlrpc_value*),
+                       valPP);
+        break;
+
+    case 'S':
+        mkStructFromVal(envP, (xmlrpc_value*) va_arg(*args, xmlrpc_value*),
+                        valPP);
+        break;
+
+    case 'V':
+        *valPP = (xmlrpc_value*) va_arg(*args, xmlrpc_value*);
+        xmlrpc_INCREF(*valPP);
+        break;
+
+    case '(':
+        getArray(envP, formatP, ')', args, valPP);
+        if (!envP->fault_occurred) {
+            XMLRPC_ASSERT(**formatP == ')');
+            (*formatP)++;  /* Skip over closing parenthesis */
+        }
+        break;
+
+    case '{': 
+        getStruct(envP, formatP, '}', args, valPP);
+        if (!envP->fault_occurred) {
+            XMLRPC_ASSERT(**formatP == '}');
+            (*formatP)++;  /* Skip over closing brace */
+        }
+        break;
+
+    default: {
+        const char * const badCharacter = xmlrpc_makePrintableChar(formatChar);
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "Unexpected character '%s' in format string", badCharacter);
+        xmlrpc_strfree(badCharacter);
+        }
+    }
+}
+
+
+
+void
+xmlrpc_build_value_va(xmlrpc_env *    const envP,
+                      const char *    const format,
+                      va_list               args,
+                      xmlrpc_value ** const valPP,
+                      const char **   const tailP) {
+
+    const char * formatCursor;
+    va_list args_copy;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(format != NULL);
+
+    if (strlen(format) == 0)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, "Format string is empty.");
+    else {
+        formatCursor = &format[0];
+        VA_LIST_COPY(args_copy, args);
+        getValue(envP, &formatCursor, &args_copy, valPP);
+        
+        if (!envP->fault_occurred)
+            XMLRPC_ASSERT_VALUE_OK(*valPP);
+        
+        *tailP = formatCursor;
+    }
+}
+
+
+
+xmlrpc_value * 
+xmlrpc_build_value(xmlrpc_env * const envP,
+                   const char * const format, 
+                   ...) {
+
+    va_list args;
+    xmlrpc_value* retval;
+    const char * suffix;
+
+    va_start(args, format);
+    xmlrpc_build_value_va(envP, format, args, &retval, &suffix);
+    va_end(args);
+
+    if (!envP->fault_occurred) {
+        if (*suffix != '\0')
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
+                "specifier: '%s'.  There must be exactly one arument.",
+                suffix);
+    
+        if (envP->fault_occurred)
+            xmlrpc_DECREF(retval);
+    }
+    return retval;
+}
+
+
+
+
+
+/*=========================================================================
+**  Parsing XML-RPC values.
+**=========================================================================
+**  Parse an XML-RPC value based on a format string. This code is heavily
+**  inspired by Py_BuildValue from Python 1.5.2.
+*/
+
+/* Prototype for recursive invocation: */
+
+static void 
+decomposeValue(xmlrpc_env *   const env,
+               xmlrpc_value * const val,
+               const char **  const format,
+               va_list *            args,
+               xmlrpc_bool    const oldstyleMemMgmt);
+
+
+
+static void 
+parsearray(xmlrpc_env *         const env,
+           const xmlrpc_value * const array,
+           const char **        const format,
+           char                 const delimiter,
+           va_list *                  args,
+           xmlrpc_bool          const oldstyleMemMgmt) {
+
+    int size, i;
+    xmlrpc_value *item;
+
+    /* Fetch the array size. */
+    size = xmlrpc_array_size(env, array);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Loop over the items in the array. */
+    for (i = 0; i < size; i++) {
+        /* Bail out if the caller didn't care about the rest of the items. */
+        if (**format == '*')
+            break;
+
+        item = xmlrpc_array_get_item(env, array, i);
+        XMLRPC_FAIL_IF_FAULT(env);
+
+        XMLRPC_ASSERT(**format != '\0');
+        if (**format == delimiter)
+            XMLRPC_FAIL(env, XMLRPC_INDEX_ERROR, "Too many items in array");
+        decomposeValue(env, item, format, args, oldstyleMemMgmt);
+        XMLRPC_FAIL_IF_FAULT(env);
+    }
+    if (**format == '*')
+        (*format)++;
+    if (**format != delimiter)
+        XMLRPC_FAIL(env, XMLRPC_INDEX_ERROR, "Not enough items in array");
+
+           cleanup:
+    return;
+}
+
+
+
+static void 
+parsestruct(xmlrpc_env *   const env,
+            xmlrpc_value * const strct,
+            const char **  const format,
+            char           const delimiter,
+            va_list *            args,
+            xmlrpc_bool    const oldstyleMemMgmt) {
+
+    xmlrpc_value *key, *value;
+    char *keystr;
+    size_t keylen;
+
+    /* Set up error handling preconditions. */
+    key = NULL;
+
+    /* Build the members of our struct. */
+    while (**format != '*' && **format != delimiter && **format != '\0') {
+
+        /* Get our key, and skip over the ':' character. Notice the
+        ** sudden call to getValue--we're going in the opposite direction. */
+        getValue(env, format, args, &key);
+        XMLRPC_FAIL_IF_FAULT(env);
+        XMLRPC_ASSERT(**format == ':');
+        (*format)++;
+
+        /* Look up the value for our key. */
+        xmlrpc_parse_value(env, key, "s#", &keystr, &keylen);
+        XMLRPC_FAIL_IF_FAULT(env);
+        value = xmlrpc_struct_get_value_n(env, strct, keystr, keylen);
+        XMLRPC_FAIL_IF_FAULT(env);
+
+        /* Get our value, and skip over the ',' character (if present). */
+        decomposeValue(env, value, format, args, oldstyleMemMgmt);
+        XMLRPC_FAIL_IF_FAULT(env);
+        XMLRPC_ASSERT(**format == ',' || **format == delimiter);
+        if (**format == ',')
+            (*format)++;
+
+        /* Release our reference, and restore our invariant. */
+        xmlrpc_DECREF(key);
+        key = NULL;
+    }
+    if (**format == '*') {
+        (*format)++;
+        if (**format != delimiter && **format != '\0')
+            XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, 
+                        "* can appear only at the end "
+                        "of a structure format specifier");
+    } else {
+        /* Here we're supposed to fail if he didn't extract all the
+           members.  But we don't know how to determine whether he
+           specified all the members, so we always fail.
+        */
+        XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, "You must specify '*' as the "
+                    "last member of a structure in a format specifier "
+                    "used for parsing an xmlrpc_value"); 
+    }
+    XMLRPC_ASSERT(**format == delimiter || **format == '\0');
+
+cleanup:
+    if (key)
+        xmlrpc_DECREF(key);
+}
+
+
+static void
+readString(xmlrpc_env *         const envP,
+           const xmlrpc_value * const valueP,
+           const char **        const stringValueP,
+           xmlrpc_bool          const oldstyleMemMgmt) {
+
+    if (oldstyleMemMgmt) {
+        xmlrpc_read_string_old(envP, valueP, stringValueP);
+    } else
+        xmlrpc_read_string(envP, valueP, stringValueP);
+}
+
+
+
+static void
+readStringLp(xmlrpc_env *         const envP,
+             const xmlrpc_value * const valueP,
+             size_t *             const lengthP,
+             const char **        const stringValueP,
+             xmlrpc_bool          const oldstyleMemMgmt) {
+
+    if (oldstyleMemMgmt) {
+        xmlrpc_read_string_lp_old(envP, valueP, lengthP, stringValueP);
+    } else
+        xmlrpc_read_string_lp(envP, valueP, lengthP, stringValueP);
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+static void
+readStringW(xmlrpc_env *     const envP,
+            xmlrpc_value *   const valueP,
+            const wchar_t ** const stringValueP,
+            xmlrpc_bool      const oldstyleMemMgmt) {
+
+    if (oldstyleMemMgmt) {
+        xmlrpc_read_string_w_old(envP, valueP, stringValueP);
+    } else
+        xmlrpc_read_string_w(envP, valueP, stringValueP);
+}
+
+
+
+static void
+readStringWLp(xmlrpc_env *     const envP,
+              xmlrpc_value *   const valueP,
+              size_t *         const lengthP,
+              const wchar_t ** const stringValueP,
+              xmlrpc_bool      const oldstyleMemMgmt) {
+
+    if (oldstyleMemMgmt) {
+        xmlrpc_read_string_w_lp_old(envP, valueP, lengthP, stringValueP);
+    } else
+        xmlrpc_read_string_w_lp(envP, valueP, lengthP, stringValueP);
+}
+#endif
+
+
+static void
+readDatetimeStr(xmlrpc_env *         const envP,
+                const xmlrpc_value * const valueP,
+                const char **        const stringValueP,
+                xmlrpc_bool          const oldstyleMemMgmt) {
+
+    if (oldstyleMemMgmt)
+        xmlrpc_read_datetime_str_old(envP, valueP, stringValueP);
+    else
+        xmlrpc_read_datetime_str(envP, valueP, stringValueP);
+}
+
+
+
+static void
+readBase64(xmlrpc_env *           const envP,
+           const xmlrpc_value *   const valueP,
+           size_t *               const lengthP,
+           const unsigned char ** const byteStringValueP,
+           xmlrpc_bool            const oldstyleMemMgmt) {
+
+    if (oldstyleMemMgmt)
+        xmlrpc_read_base64_old(envP, valueP, lengthP, byteStringValueP);
+    else
+        xmlrpc_read_base64(envP, valueP, lengthP, byteStringValueP);
+}
+
+
+
+static void 
+decomposeValue(xmlrpc_env *   const envP,
+               xmlrpc_value * const valueP,
+               const char **  const format,
+               va_list *            args,
+               xmlrpc_bool    const oldstyleMemMgmt) {
+
+    char formatSpecChar;
+
+    formatSpecChar = *(*format)++;
+
+    switch (formatSpecChar) {
+    case 'i': {
+        xmlrpc_int32 * const int32ptr = 
+            (xmlrpc_int32*) va_arg(*args, xmlrpc_int32*);
+        xmlrpc_read_int(envP, valueP, int32ptr);
+        }
+    break;
+
+    case 'b': {
+        xmlrpc_bool * const boolptr =
+            (xmlrpc_bool*) va_arg(*args, xmlrpc_bool*);
+        xmlrpc_read_bool(envP, valueP, boolptr);
+    }
+    break;
+
+    case 'd': {
+        double * const doubleptr = (double*) va_arg(*args, double*);
+        xmlrpc_read_double(envP, valueP, doubleptr);
+    }
+    break;
+
+    case '8': {
+        /* The code 't' is reserved for a better, time_t based
+           implementation of dateTime conversion. 
+        */
+        const char ** const strptr = (const char**) va_arg(*args, char**);
+        readDatetimeStr(envP, valueP, strptr, oldstyleMemMgmt);
+    }
+    break;
+
+    case 's': {
+        const char ** const strptr = (const char**) va_arg(*args, char**);
+        if (**format == '#') {
+            size_t * const sizeptr = (size_t*) va_arg(*args, size_t**);
+            (*format)++;
+
+            readStringLp(envP, valueP, sizeptr, strptr, oldstyleMemMgmt);
+        } else
+            readString(envP, valueP, strptr, oldstyleMemMgmt);
+    }
+    break;
+
+    case 'w': {
+#if HAVE_UNICODE_WCHAR
+        const wchar_t ** const wcsptr = 
+            (const wchar_t**) va_arg(*args, wchar_t**);
+        if (**format == '#') {
+            size_t * const sizeptr = (size_t*) va_arg(*args, size_t**);
+            (*format)++;
+            readStringWLp(envP, valueP, sizeptr, wcsptr, oldstyleMemMgmt);
+        } else
+            readStringW(envP, valueP, wcsptr, oldstyleMemMgmt);
+#else
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "This XML-RPC For C/C++ library was built without Unicode "
+            "wide character capability.  'w' isn't available.");
+#endif /* HAVE_UNICODE_WCHAR */
+    }
+    break;
+        
+    case '6': {
+        const unsigned char ** const binptr =
+            (const unsigned char**) va_arg(*args, unsigned char**);
+        size_t * const sizeptr = (size_t*) va_arg(*args, size_t**);        
+        readBase64(envP, valueP, sizeptr, binptr, oldstyleMemMgmt);
+    }
+    break;
+
+    case 'n': {
+        xmlrpc_read_nil(envP, valueP);
+    }
+    break;
+
+    case 'p': {
+        void ** const voidptrptr = (void**) va_arg(*args, void**);
+        xmlrpc_read_cptr(envP, valueP, voidptrptr);
+    }
+    break;
+
+    case 'V': {
+        xmlrpc_value ** const valptr =
+            (xmlrpc_value**) va_arg(*args, xmlrpc_value**);
+        *valptr = valueP;
+        if (!oldstyleMemMgmt)
+            xmlrpc_INCREF(valueP);
+    }
+    break;
+
+    case 'A':
+        if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_ARRAY)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_TYPE_ERROR, "Non-array type supplied for "
+                "'A' specifier");
+        else {
+            xmlrpc_value ** const valptr =
+                (xmlrpc_value**) va_arg(*args, xmlrpc_value**);
+            *valptr = valueP;
+            if (!oldstyleMemMgmt)
+                xmlrpc_INCREF(valueP);
+        }
+        break;
+
+    case 'S':
+        if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_STRUCT)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_TYPE_ERROR, "Non-struct type supplied for "
+                "'S' specifier");
+        else {
+            xmlrpc_value ** const valptr =
+                (xmlrpc_value**) va_arg(*args, xmlrpc_value**);
+            *valptr = valueP;
+            if (!oldstyleMemMgmt)
+                xmlrpc_INCREF(valueP);
+        }
+        break;
+
+    case '(':
+        if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_ARRAY)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_TYPE_ERROR, "Non-array type supplied for "
+                "'()' specifier");
+        else {
+            parsearray(envP, valueP, format, ')', args, oldstyleMemMgmt);
+            (*format)++;
+        }
+        break;
+
+    case '{':
+        if (xmlrpc_value_type(valueP) != XMLRPC_TYPE_STRUCT)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_TYPE_ERROR, "Non-struct type supplied for "
+                "'{}' specifier");
+        else {
+            parsestruct(envP, valueP, format, '}', args, oldstyleMemMgmt);
+            (*format)++;
+        }
+        break;
+
+    default:
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, "Invalid format character '%c'",
+            formatSpecChar);
+    }
+}
+
+
+
+void 
+xmlrpc_decompose_value_va(xmlrpc_env *   const envP,
+                          xmlrpc_value * const value,
+                          const char *   const format,
+                          va_list              args) {
+
+    const char *format_copy;
+    va_list args_copy;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(value);
+    XMLRPC_ASSERT(format != NULL);
+
+    format_copy = format;
+    VA_LIST_COPY(args_copy, args);
+    decomposeValue(envP, value, &format_copy, &args_copy, false);
+    if (!envP->fault_occurred) {
+        XMLRPC_ASSERT(*format_copy == '\0');
+    }
+}
+
+
+
+void 
+xmlrpc_decompose_value(xmlrpc_env *   const envP,
+                       xmlrpc_value * const value,
+                       const char *   const format, 
+                       ...) {
+
+    va_list args;
+
+    va_start(args, format);
+    xmlrpc_decompose_value_va(envP, value, format, args);
+    va_end(args);
+}
+
+
+
+void 
+xmlrpc_parse_value_va(xmlrpc_env *   const envP,
+                      xmlrpc_value * const value,
+                      const char *   const format,
+                      va_list              args) {
+
+    const char *format_copy;
+    va_list args_copy;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(value);
+    XMLRPC_ASSERT(format != NULL);
+
+    format_copy = format;
+    VA_LIST_COPY(args_copy, args);
+    decomposeValue(envP, value, &format_copy, &args_copy, true);
+    if (!envP->fault_occurred) {
+        XMLRPC_ASSERT(*format_copy == '\0');
+    }
+}
+
+
+
+void 
+xmlrpc_parse_value(xmlrpc_env *   const envP,
+                   xmlrpc_value * const value,
+                   const char *   const format, 
+                   ...) {
+
+    va_list args;
+
+    va_start(args, format);
+    xmlrpc_parse_value_va(envP, value, format, args);
+    va_end(args);
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2001 by Eric Kidd. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/src/xmlrpc_client.c b/src/xmlrpc_client.c
new file mode 100644 (file)
index 0000000..5edaa9f
--- /dev/null
@@ -0,0 +1,1011 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#undef PACKAGE
+#undef VERSION
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/client.h"
+#include "xmlrpc-c/client_int.h"
+/* transport_config.h defines XMLRPC_DEFAULT_TRANSPORT,
+    MUST_BUILD_WININET_CLIENT, MUST_BUILD_CURL_CLIENT,
+    MUST_BUILD_LIBWWW_CLIENT 
+*/
+#include "transport_config.h"
+
+#if MUST_BUILD_WININET_CLIENT
+#include "xmlrpc_wininet_transport.h"
+#endif
+#if MUST_BUILD_CURL_CLIENT
+#include "xmlrpc_curl_transport.h"
+#endif
+#if MUST_BUILD_LIBWWW_CLIENT
+#include "xmlrpc_libwww_transport.h"
+#endif
+
+struct xmlrpc_client {
+/*----------------------------------------------------------------------------
+   This represents a client object.
+-----------------------------------------------------------------------------*/
+    struct xmlrpc_client_transport *   transportP;
+    struct xmlrpc_client_transport_ops clientTransportOps;
+};
+
+
+
+typedef struct xmlrpc_call_info {
+    /* These fields are used when performing asynchronous calls.
+    ** The _asynch_data_holder contains server_url, method_name and
+    ** param_array, so it's the only thing we need to free. */
+    xmlrpc_value *_asynch_data_holder;
+    char *server_url;
+    char *method_name;
+    xmlrpc_value *param_array;
+    xmlrpc_response_handler callback;
+    void *user_data;
+
+    /* The serialized XML data passed to this call. We keep this around
+    ** for use by our source_anchor field. */
+    xmlrpc_mem_block *serialized_xml;
+} xmlrpc_call_info;
+
+
+
+/*=========================================================================
+   Global Constant Setup/Teardown
+=========================================================================*/
+
+static void
+callTransportSetup(xmlrpc_env *           const envP,
+                   xmlrpc_transport_setup       setupFn) {
+
+    if (setupFn)
+        setupFn(envP);
+}
+
+
+
+static void
+setupTransportGlobalConst(xmlrpc_env * const envP) {
+
+#if MUST_BUILD_WININET_CLIENT
+    if (!envP->fault_occurred)
+        callTransportSetup(envP,
+                           xmlrpc_wininet_transport_ops.setup_global_const);
+#endif
+#if MUST_BUILD_CURL_CLIENT
+    if (!envP->fault_occurred)
+        callTransportSetup(envP,
+                           xmlrpc_curl_transport_ops.setup_global_const);
+#endif
+#if MUST_BUILD_LIBWWW_CLIENT
+    if (!envP->fault_occurred)
+        callTransportSetup(envP,
+                           xmlrpc_libwww_transport_ops.setup_global_const);
+#endif
+}
+
+
+
+static void
+callTransportTeardown(xmlrpc_transport_teardown teardownFn) {
+
+    if (teardownFn)
+        teardownFn();
+}
+
+
+
+static void
+teardownTransportGlobalConst(void) {
+
+#if MUST_BUILD_WININET_CLIENT
+    callTransportTeardown(
+        xmlrpc_wininet_transport_ops.teardown_global_const);
+#endif
+#if MUST_BUILD_CURL_CLIENT
+    callTransportTeardown(
+        xmlrpc_curl_transport_ops.teardown_global_const);
+#endif
+#if MUST_BUILD_LIBWWW_CLIENT
+    callTransportTeardown(
+        xmlrpc_libwww_transport_ops.teardown_global_const);
+#endif
+}
+
+
+
+static unsigned int constSetupCount = 0;
+
+
+void
+xmlrpc_client_setup_global_const(xmlrpc_env * const envP) {
+/*----------------------------------------------------------------------------
+   Set up pseudo-constant global variables (they'd be constant, except that
+   the library loader doesn't set them.  An explicit call from the loaded
+   program does).
+
+   This function is not thread-safe.  The user is supposed to call it
+   (perhaps cascaded down from a multitude of higher level libraries)
+   as part of early program setup, when the program is only one thread.
+-----------------------------------------------------------------------------*/
+    if (constSetupCount == 0)
+        setupTransportGlobalConst(envP);
+
+    ++constSetupCount;
+}
+
+
+
+void
+xmlrpc_client_teardown_global_const(void) {
+/*----------------------------------------------------------------------------
+   Complement to xmlrpc_client_setup_global_const().
+
+   This function is not thread-safe.  The user is supposed to call it
+   (perhaps cascaded down from a multitude of higher level libraries)
+   as part of final program cleanup, when the program is only one thread.
+-----------------------------------------------------------------------------*/
+    assert(constSetupCount > 0);
+
+    --constSetupCount;
+
+    if (constSetupCount == 0)
+        teardownTransportGlobalConst();
+}
+
+
+
+/*=========================================================================
+   Client Create/Destroy
+=========================================================================*/
+
+static void
+getTransportOps(xmlrpc_env *                         const envP,
+                const char *                         const transportName,
+                struct xmlrpc_client_transport_ops * const opsP) {
+
+    if (false) {
+    }
+#if MUST_BUILD_WININET_CLIENT
+    else if (strcmp(transportName, "wininet") == 0)
+        *opsP = xmlrpc_wininet_transport_ops;
+#endif
+#if MUST_BUILD_CURL_CLIENT
+    else if (strcmp(transportName, "curl") == 0)
+        *opsP = xmlrpc_curl_transport_ops;
+#endif
+#if MUST_BUILD_LIBWWW_CLIENT
+    else if (strcmp(transportName, "libwww") == 0)
+        *opsP = xmlrpc_libwww_transport_ops;
+#endif
+    else
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR, 
+            "Unrecognized XML transport name '%s'", transportName);
+}
+
+
+
+static void
+getTransportParmsFromClientParms(
+    xmlrpc_env *                      const envP,
+    const struct xmlrpc_clientparms * const clientparmsP,
+    unsigned int                      const parmSize,
+    const struct xmlrpc_xportparms ** const transportparmsPP,
+    size_t *                          const transportparmSizeP) {
+
+    if (parmSize < XMLRPC_CPSIZE(transportparmsP) ||
+        clientparmsP->transportparmsP == NULL) {
+
+        *transportparmsPP = NULL;
+        *transportparmSizeP = 0;
+    } else {
+        *transportparmsPP = clientparmsP->transportparmsP;
+        if (parmSize < XMLRPC_CPSIZE(transportparm_size))
+            xmlrpc_faultf(envP, "Your 'clientparms' argument contains the "
+                          "transportparmsP member, "
+                          "but no transportparms_size member");
+        else
+            *transportparmSizeP = clientparmsP->transportparm_size;
+    }
+}
+
+
+
+static void
+getTransportInfo(xmlrpc_env *                      const envP,
+                 const struct xmlrpc_clientparms * const clientparmsP,
+                 unsigned int                      const parmSize,
+                 const char **                     const transportNameP,
+                 const struct xmlrpc_xportparms ** const transportparmsPP,
+                 size_t *                          const transportparmSizeP) {
+
+    getTransportParmsFromClientParms(
+        envP, clientparmsP, parmSize, 
+        transportparmsPP, transportparmSizeP);
+    
+    if (!envP->fault_occurred) {
+        if (parmSize < XMLRPC_CPSIZE(transport) ||
+            clientparmsP->transport == NULL) {
+
+            /* He didn't specify a transport class.  Use the default */
+
+            *transportNameP = xmlrpc_client_get_default_transport(envP);
+            if (*transportparmsPP)
+                xmlrpc_faultf(envP,
+                    "You specified transport parameters, but did not "
+                    "specify a transport type.  Parameters are specific to "
+                    "a particular type.");
+        } else
+            *transportNameP = clientparmsP->transport;
+    }
+}
+
+
+
+void 
+xmlrpc_client_create(xmlrpc_env *                      const envP,
+                     int                               const flags,
+                     const char *                      const appname,
+                     const char *                      const appversion,
+                     const struct xmlrpc_clientparms * const clientparmsP,
+                     unsigned int                      const parmSize,
+                     xmlrpc_client **                  const clientPP) {
+    
+    XMLRPC_ASSERT_PTR_OK(clientPP);
+
+    if (constSetupCount == 0) {
+        xmlrpc_faultf(envP,
+                      "You have not called "
+                      "xmlrpc_client_setup_global_const().");
+        /* Impl note:  We can't just call it now because it isn't
+           thread-safe.
+        */
+    } else {
+        xmlrpc_client * clientP;
+
+        MALLOCVAR(clientP);
+
+        if (clientP == NULL)
+            xmlrpc_faultf(envP, "Unable to allocate memory for "
+                          "client descriptor.");
+        else {
+            const char * transportName;
+            const struct xmlrpc_xportparms * transportparmsP;
+            size_t transportparmSize;
+        
+            getTransportInfo(envP, clientparmsP, parmSize, &transportName, 
+                             &transportparmsP, &transportparmSize);
+            
+            if (!envP->fault_occurred) {
+                getTransportOps(envP, transportName,
+                                &clientP->clientTransportOps);
+                if (!envP->fault_occurred) {
+                    /* The following call is not thread-safe */
+                    clientP->clientTransportOps.create(
+                        envP, flags, appname, appversion,
+                        transportparmsP, transportparmSize,
+                        &clientP->transportP);
+                    if (!envP->fault_occurred)
+                        *clientPP = clientP;
+                }
+            }
+            if (envP->fault_occurred)
+                free(clientP);
+        }
+    }
+}
+
+
+
+void 
+xmlrpc_client_destroy(xmlrpc_client * const clientP) {
+
+    XMLRPC_ASSERT_PTR_OK(clientP);
+
+    clientP->clientTransportOps.destroy(clientP->transportP);
+
+    free(clientP);
+}
+
+
+
+/*=========================================================================
+   Call/Response Utilities
+=========================================================================*/
+
+static void
+makeCallXml(xmlrpc_env *               const envP,
+            const char *               const methodName,
+            xmlrpc_value *             const paramArrayP,
+            xmlrpc_mem_block **        const callXmlPP) {
+
+    XMLRPC_ASSERT_VALUE_OK(paramArrayP);
+    XMLRPC_ASSERT_PTR_OK(callXmlPP);
+
+    if (methodName == NULL)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "method name argument is NULL pointer");
+    else {
+        xmlrpc_mem_block * callXmlP;
+
+        callXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+        if (!envP->fault_occurred) {
+            xmlrpc_serialize_call(envP, callXmlP, methodName, paramArrayP);
+
+            *callXmlPP = callXmlP;
+
+            if (envP->fault_occurred)
+                XMLRPC_MEMBLOCK_FREE(char, callXmlP);
+        }
+    }    
+}
+
+
+
+/*=========================================================================
+    xmlrpc_server_info
+=========================================================================*/
+
+xmlrpc_server_info *
+xmlrpc_server_info_new(xmlrpc_env * const envP,
+                       const char * const serverUrl) {
+    
+    xmlrpc_server_info * serverInfoP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(serverUrl);
+
+    /* Allocate our memory blocks. */
+    MALLOCVAR(serverInfoP);
+    if (serverInfoP == NULL)
+        xmlrpc_faultf(envP, "Couldn't allocate memory for xmlrpc_server_info");
+    else {
+        memset(serverInfoP, 0, sizeof(xmlrpc_server_info));
+
+        serverInfoP->_server_url = strdup(serverUrl);
+        if (serverInfoP->_server_url == NULL)
+            xmlrpc_faultf(envP, "Couldn't allocate memory for server URL");
+        else {
+            serverInfoP->_http_basic_auth = NULL;
+            if (envP->fault_occurred)
+                xmlrpc_strfree(serverInfoP->_server_url);
+        }
+        if (envP->fault_occurred)
+            free(serverInfoP);
+    }
+    return serverInfoP;
+}
+
+
+
+xmlrpc_server_info *
+xmlrpc_server_info_copy(xmlrpc_env *         const envP,
+                        xmlrpc_server_info * const aserverInfoP) {
+
+    xmlrpc_server_info * serverInfoP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(aserverInfoP);
+
+    MALLOCVAR(serverInfoP);
+    if (serverInfoP == NULL)
+        xmlrpc_faultf(envP,
+                      "Couldn't allocate memory for xmlrpc_server_info");
+    else {
+        serverInfoP->_server_url = strdup(aserverInfoP->_server_url);
+        if (serverInfoP->_server_url == NULL)
+            xmlrpc_faultf(envP, "Couldn't allocate memory for server URL");
+        else {
+            if (aserverInfoP->_http_basic_auth == NULL)
+                serverInfoP->_http_basic_auth = NULL;
+            else {
+                serverInfoP->_http_basic_auth =
+                    strdup(aserverInfoP->_http_basic_auth);
+                if (serverInfoP->_http_basic_auth == NULL)
+                    xmlrpc_faultf(envP, "Couldn't allocate memory "
+                                  "for authentication info");
+            }
+            if (envP->fault_occurred)
+                xmlrpc_strfree(serverInfoP->_server_url);
+        }
+        if (envP->fault_occurred)
+            free(serverInfoP);
+    }
+    return serverInfoP;
+}
+
+
+
+void
+xmlrpc_server_info_free(xmlrpc_server_info * const serverInfoP) {
+
+    XMLRPC_ASSERT_PTR_OK(serverInfoP);
+    XMLRPC_ASSERT(serverInfoP->_server_url != XMLRPC_BAD_POINTER);
+
+    if (serverInfoP->_http_basic_auth)
+        free(serverInfoP->_http_basic_auth);
+    serverInfoP->_http_basic_auth = XMLRPC_BAD_POINTER;
+    free(serverInfoP->_server_url);
+    serverInfoP->_server_url = XMLRPC_BAD_POINTER;
+    free(serverInfoP);
+}
+
+
+
+/*=========================================================================
+   Synchronous Call
+=========================================================================*/
+
+void
+xmlrpc_client_transport_call2(
+    xmlrpc_env *               const envP,
+    xmlrpc_client *            const clientP,
+    const xmlrpc_server_info * const serverP,
+    xmlrpc_mem_block *         const callXmlP,
+    xmlrpc_mem_block **        const respXmlPP) {
+
+    XMLRPC_ASSERT_PTR_OK(clientP);
+    XMLRPC_ASSERT_PTR_OK(serverP);
+    XMLRPC_ASSERT_PTR_OK(callXmlP);
+    XMLRPC_ASSERT_PTR_OK(respXmlPP);
+
+    clientP->clientTransportOps.call(
+        envP, clientP->transportP, serverP, callXmlP,
+        respXmlPP);
+}
+
+
+
+void
+xmlrpc_client_call2(xmlrpc_env *               const envP,
+                    struct xmlrpc_client *     const clientP,
+                    const xmlrpc_server_info * const serverInfoP,
+                    const char *               const methodName,
+                    xmlrpc_value *             const paramArrayP,
+                    xmlrpc_value **            const resultPP) {
+
+    xmlrpc_mem_block * callXmlP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(clientP);
+    XMLRPC_ASSERT_PTR_OK(serverInfoP);
+    XMLRPC_ASSERT_PTR_OK(paramArrayP);
+
+    makeCallXml(envP, methodName, paramArrayP, &callXmlP);
+    
+    if (!envP->fault_occurred) {
+        xmlrpc_mem_block * respXmlP;
+        
+        xmlrpc_traceXml("XML-RPC CALL", 
+                        XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP),
+                        XMLRPC_MEMBLOCK_SIZE(char, callXmlP));
+        
+        clientP->clientTransportOps.call(
+            envP, clientP->transportP, serverInfoP, callXmlP, &respXmlP);
+        if (!envP->fault_occurred) {
+            int faultCode;
+            const char * faultString;
+
+            xmlrpc_traceXml("XML-RPC RESPONSE", 
+                            XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP),
+                            XMLRPC_MEMBLOCK_SIZE(char, respXmlP));
+            
+            xmlrpc_parse_response2(
+                envP,
+                XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP),
+                XMLRPC_MEMBLOCK_SIZE(char, respXmlP),
+                resultPP, &faultCode, &faultString);
+
+            if (!envP->fault_occurred) {
+                if (faultString) {
+                    xmlrpc_env_set_fault_formatted(
+                        envP, faultCode,
+                        "RPC failed at server.  %s", faultString);
+                    xmlrpc_strfree(faultString);
+                } else
+                    XMLRPC_ASSERT_VALUE_OK(*resultPP);
+            }
+            XMLRPC_MEMBLOCK_FREE(char, respXmlP);
+        }
+        XMLRPC_MEMBLOCK_FREE(char, callXmlP);
+    }
+}
+
+
+
+static void
+clientCall2f_va(xmlrpc_env *               const envP,
+                xmlrpc_client *            const clientP,
+                const char *               const serverUrl,
+                const char *               const methodName,
+                const char *               const format,
+                xmlrpc_value **            const resultPP,
+                va_list                          args) {
+
+    xmlrpc_value * argP;
+    xmlrpc_env argenv;
+    const char * suffix;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(serverUrl);
+    XMLRPC_ASSERT_PTR_OK(methodName);
+    XMLRPC_ASSERT_PTR_OK(format);
+    XMLRPC_ASSERT_PTR_OK(resultPP);
+
+    /* Build our argument value. */
+    xmlrpc_env_init(&argenv);
+    xmlrpc_build_value_va(&argenv, format, args, &argP, &suffix);
+    if (argenv.fault_occurred)
+        xmlrpc_env_set_fault_formatted(
+            envP, argenv.fault_code, "Invalid RPC arguments.  "
+            "The format argument must indicate a single array, and the "
+            "following arguments must correspond to that format argument.  "
+            "The failure is: %s",
+            argenv.fault_string);
+    else {
+        XMLRPC_ASSERT_VALUE_OK(argP);
+        
+        if (*suffix != '\0')
+            xmlrpc_faultf(envP, "Junk after the argument specifier: '%s'.  "
+                          "There must be exactly one argument.",
+                          suffix);
+        else {
+            xmlrpc_server_info * serverInfoP;
+
+            serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+            
+            if (!envP->fault_occurred) {
+                /* Perform the actual XML-RPC call. */
+                xmlrpc_client_call2(envP, clientP,
+                                    serverInfoP, methodName, argP, resultPP);
+                if (!envP->fault_occurred)
+                    XMLRPC_ASSERT_VALUE_OK(*resultPP);
+                xmlrpc_server_info_free(serverInfoP);
+            }
+        }
+        xmlrpc_DECREF(argP);
+    }
+    xmlrpc_env_clean(&argenv);
+}
+
+
+
+void
+xmlrpc_client_call2f(xmlrpc_env *    const envP,
+                     xmlrpc_client * const clientP,
+                     const char *    const serverUrl,
+                     const char *    const methodName,
+                     xmlrpc_value ** const resultPP,
+                     const char *    const format,
+                     ...) {
+
+    va_list args;
+
+    va_start(args, format);
+    clientCall2f_va(envP, clientP, serverUrl,
+                    methodName, format, resultPP, args);
+    va_end(args);
+}
+
+
+
+/*=========================================================================
+   Asynchronous Call
+=========================================================================*/
+
+static void 
+call_info_set_asynch_data(xmlrpc_env *       const env,
+                          xmlrpc_call_info * const info,
+                          const char *       const server_url,
+                          const char *       const method_name,
+                          xmlrpc_value *     const argP,
+                          xmlrpc_response_handler responseHandler,
+                          void *             const user_data) {
+
+    xmlrpc_value *holder;
+
+    /* Error-handling preconditions. */
+    holder = NULL;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_PTR_OK(info);
+    XMLRPC_ASSERT(info->_asynch_data_holder == NULL);
+    XMLRPC_ASSERT_PTR_OK(server_url);
+    XMLRPC_ASSERT_PTR_OK(method_name);
+    XMLRPC_ASSERT_VALUE_OK(argP);
+
+    /* Install our callback and user_data.
+    ** (We're not responsible for destroying the user_data.) */
+    info->callback  = responseHandler;
+    info->user_data = user_data;
+
+    /* Build an XML-RPC data structure to hold our other data. This makes
+    ** copies of server_url and method_name, and increments the reference
+    ** to the argument *argP. */
+    holder = xmlrpc_build_value(env, "(ssV)",
+                                server_url, method_name, argP);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Parse the newly-allocated structure into our public member variables.
+    ** This doesn't make any new references, so we can dispose of the whole
+    ** thing by DECREF'ing the one master reference. Nifty, huh? */
+    xmlrpc_parse_value(env, holder, "(ssV)",
+                       &info->server_url,
+                       &info->method_name,
+                       &info->param_array);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Hand over ownership of the holder to the call_info struct. */
+    info->_asynch_data_holder = holder;
+    holder = NULL;
+
+ cleanup:
+    if (env->fault_occurred) {
+        if (holder)
+            xmlrpc_DECREF(holder);
+    }
+}
+
+
+
+static void 
+call_info_free(xmlrpc_call_info * const callInfoP) {
+
+    /* Assume the worst.. That only parts of the call_info are valid. */
+
+    XMLRPC_ASSERT_PTR_OK(callInfoP);
+
+    /* If this has been allocated, we're responsible for destroying it. */
+    if (callInfoP->_asynch_data_holder)
+        xmlrpc_DECREF(callInfoP->_asynch_data_holder);
+
+    /* Now we can blow away the XML data. */
+    if (callInfoP->serialized_xml)
+         xmlrpc_mem_block_free(callInfoP->serialized_xml);
+
+    free(callInfoP);
+}
+
+
+
+static void
+call_info_new(xmlrpc_env *               const envP,
+              const char *               const methodName,
+              xmlrpc_value *             const paramArrayP,
+              xmlrpc_call_info **        const callInfoPP) {
+/*----------------------------------------------------------------------------
+   Create a call_info object.  A call_info object represents an XML-RPC
+   call.
+-----------------------------------------------------------------------------*/
+    struct xmlrpc_call_info * callInfoP;
+
+    XMLRPC_ASSERT_PTR_OK(paramArrayP);
+    XMLRPC_ASSERT_PTR_OK(callInfoPP);
+
+    MALLOCVAR(callInfoP);
+    if (callInfoP == NULL)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "Couldn't allocate memory for xmlrpc_call_info");
+    else {
+        xmlrpc_mem_block * callXmlP;
+
+        /* Clear contents. */
+        memset(callInfoP, 0, sizeof(*callInfoP));
+        
+        makeCallXml(envP, methodName, paramArrayP, &callXmlP);
+
+        if (!envP->fault_occurred) {
+            xmlrpc_traceXml("XML-RPC CALL", 
+                            XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP),
+                            XMLRPC_MEMBLOCK_SIZE(char, callXmlP));
+            
+            callInfoP->serialized_xml = callXmlP;
+            
+            *callInfoPP = callInfoP;
+
+            if (envP->fault_occurred)
+                free(callInfoP);
+        }
+    }
+}
+
+
+
+void 
+xmlrpc_client_event_loop_finish(xmlrpc_client * const clientP) {
+
+    XMLRPC_ASSERT_PTR_OK(clientP);
+
+    clientP->clientTransportOps.finish_asynch(
+        clientP->transportP, timeout_no, 0);
+}
+
+
+
+void 
+xmlrpc_client_event_loop_finish_timeout(xmlrpc_client * const clientP,
+                                        xmlrpc_timeout  const timeout) {
+
+    XMLRPC_ASSERT_PTR_OK(clientP);
+
+    clientP->clientTransportOps.finish_asynch(
+        clientP->transportP, timeout_yes, timeout);
+}
+
+
+
+static void
+asynchComplete(struct xmlrpc_call_info * const callInfoP,
+               xmlrpc_mem_block *        const responseXmlP,
+               xmlrpc_env                const transportEnv) {
+/*----------------------------------------------------------------------------
+   Complete an asynchronous XML-RPC call request.
+
+   This includes calling the user's RPC completion routine.
+
+   'transportEnv' describes an error that the transport
+   encountered in processing the call.  If the transport successfully
+   sent the call to the server and processed the response but the
+   server failed the call, 'transportEnv' indicates no error, and the
+   response in *responseXmlP might very well indicate that the server
+   failed the request.
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+    xmlrpc_value * resultP;
+
+    xmlrpc_env_init(&env);
+
+    resultP = NULL;  /* Just to quiet compiler warning */
+
+    if (transportEnv.fault_occurred)
+        xmlrpc_env_set_fault_formatted(
+            &env, transportEnv.fault_code,
+            "Client transport failed to execute the RPC.  %s",
+            transportEnv.fault_string);
+
+    if (!env.fault_occurred) {
+        int faultCode;
+        const char * faultString;
+
+        xmlrpc_parse_response2(&env,
+                               XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlP),
+                               XMLRPC_MEMBLOCK_SIZE(char, responseXmlP),
+                               &resultP, &faultCode, &faultString);
+
+        if (!env.fault_occurred) {
+            if (faultString) {
+                xmlrpc_env_set_fault_formatted(
+                    &env, faultCode,
+                    "RPC failed at server.  %s", faultString);
+                xmlrpc_strfree(faultString);
+            }
+        }
+    }
+    /* Call the user's callback function with the result */
+    (*callInfoP->callback)(callInfoP->server_url, 
+                           callInfoP->method_name, 
+                           callInfoP->param_array,
+                           callInfoP->user_data, &env, resultP);
+
+    if (!env.fault_occurred)
+        xmlrpc_DECREF(resultP);
+
+    call_info_free(callInfoP);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_client_start_rpc(xmlrpc_env *             const envP,
+                        struct xmlrpc_client *   const clientP,
+                        xmlrpc_server_info *     const serverInfoP,
+                        const char *             const methodName,
+                        xmlrpc_value *           const argP,
+                        xmlrpc_response_handler        responseHandler,
+                        void *                   const userData) {
+    
+    xmlrpc_call_info * callInfoP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(clientP);
+    XMLRPC_ASSERT_PTR_OK(serverInfoP);
+    XMLRPC_ASSERT_PTR_OK(methodName);
+    XMLRPC_ASSERT_PTR_OK(responseHandler);
+    XMLRPC_ASSERT_VALUE_OK(argP);
+
+    call_info_new(envP, methodName, argP, &callInfoP);
+    if (!envP->fault_occurred) {
+        call_info_set_asynch_data(envP, callInfoP, 
+                                  serverInfoP->_server_url, methodName,
+                                  argP, responseHandler, userData);
+        if (!envP->fault_occurred)
+            clientP->clientTransportOps.send_request(
+                envP, clientP->transportP, serverInfoP,
+                callInfoP->serialized_xml,
+                &asynchComplete, callInfoP);
+
+        if (envP->fault_occurred)
+            call_info_free(callInfoP);
+        else {
+            /* asynchComplete() will free *callInfoP */
+        }
+    }
+}
+
+
+
+void 
+xmlrpc_client_start_rpcf(xmlrpc_env *    const envP,
+                         xmlrpc_client * const clientP,
+                         const char *    const serverUrl,
+                         const char *    const methodName,
+                         xmlrpc_response_handler responseHandler,
+                         void *          const userData,
+                         const char *    const format,
+                         ...) {
+
+    va_list args;
+    xmlrpc_value * paramArrayP;
+    const char * suffix;
+
+    XMLRPC_ASSERT_PTR_OK(serverUrl);
+    XMLRPC_ASSERT_PTR_OK(format);
+
+    /* Build our argument array. */
+    va_start(args, format);
+    xmlrpc_build_value_va(envP, format, args, &paramArrayP, &suffix);
+    va_end(args);
+    if (!envP->fault_occurred) {
+        if (*suffix != '\0')
+            xmlrpc_faultf(envP, "Junk after the argument "
+                          "specifier: '%s'.  "
+                          "There must be exactly one arument.",
+                          suffix);
+        else {
+            xmlrpc_server_info * serverInfoP;
+
+            serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+            if (!envP->fault_occurred) {
+                xmlrpc_client_start_rpc(
+                    envP, clientP,
+                    serverInfoP, methodName, paramArrayP,
+                    responseHandler, userData);
+            }
+            xmlrpc_server_info_free(serverInfoP);
+        }
+        xmlrpc_DECREF(paramArrayP);
+    }
+}
+
+
+
+/*=========================================================================
+   Miscellaneous
+=========================================================================*/
+
+void 
+xmlrpc_server_info_set_basic_auth(xmlrpc_env *         const envP,
+                                  xmlrpc_server_info * const serverP,
+                                  const char *         const username,
+                                  const char *         const password) {
+
+    size_t username_len, password_len, raw_token_len;
+    char *raw_token;
+    xmlrpc_mem_block *token;
+    char *token_data, *auth_type, *auth_header;
+    size_t token_len, auth_type_len, auth_header_len;
+
+    /* Error-handling preconditions. */
+    raw_token = NULL;
+    token = NULL;
+    token_data = auth_type = auth_header = NULL;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_PTR_OK(serverP);
+    XMLRPC_ASSERT_PTR_OK(username);
+    XMLRPC_ASSERT_PTR_OK(password);
+
+    /* Calculate some lengths. */
+    username_len = strlen(username);
+    password_len = strlen(password);
+    raw_token_len = username_len + password_len + 1;
+
+    /* Build a raw token of the form 'username:password'. */
+    raw_token = (char*) malloc(raw_token_len + 1);
+    XMLRPC_FAIL_IF_NULL(raw_token, envP, XMLRPC_INTERNAL_ERROR,
+                        "Couldn't allocate memory for auth token");
+    strcpy(raw_token, username);
+    raw_token[username_len] = ':';
+    strcpy(&raw_token[username_len + 1], password);
+
+    /* Encode our raw token using Base64. */
+    token = xmlrpc_base64_encode_without_newlines(envP, 
+                                                  (unsigned char*) raw_token,
+                                                  raw_token_len);
+    XMLRPC_FAIL_IF_FAULT(envP);
+    token_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, token);
+    token_len = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, token);
+
+    /* Build our actual header value. (I hate string processing in C.) */
+    auth_type = "Basic ";
+    auth_type_len = strlen(auth_type);
+    auth_header_len = auth_type_len + token_len;
+    auth_header = (char*) malloc(auth_header_len + 1);
+    XMLRPC_FAIL_IF_NULL(auth_header, envP, XMLRPC_INTERNAL_ERROR,
+                        "Couldn't allocate memory for auth header");
+    memcpy(auth_header, auth_type, auth_type_len);
+    memcpy(&auth_header[auth_type_len], token_data, token_len);
+    auth_header[auth_header_len] = '\0';
+
+    /* Clean up any pre-existing authentication information, and install
+    ** the new value. */
+    if (serverP->_http_basic_auth)
+        free(serverP->_http_basic_auth);
+    serverP->_http_basic_auth = auth_header;
+
+ cleanup:
+    if (raw_token)
+        free(raw_token);
+    if (token)
+        xmlrpc_mem_block_free(token);
+    if (envP->fault_occurred) {
+        if (auth_header)
+            free(auth_header);
+    }
+}
+
+
+
+const char * 
+xmlrpc_client_get_default_transport(xmlrpc_env * const env ATTR_UNUSED) {
+
+    return XMLRPC_DEFAULT_TRANSPORT;
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
diff --git a/src/xmlrpc_client_global.c b/src/xmlrpc_client_global.c
new file mode 100644 (file)
index 0000000..1928b9a
--- /dev/null
@@ -0,0 +1,414 @@
+#include <stdarg.h>
+
+#include "xmlrpc_config.h"
+
+#include "bool.h"
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+#include <xmlrpc-c/client_int.h>
+#include <xmlrpc-c/client_global.h>
+
+/*=========================================================================
+   Global Client
+=========================================================================*/
+
+static struct xmlrpc_client * globalClientP;
+static bool globalClientExists = false;
+
+
+void 
+xmlrpc_client_init2(xmlrpc_env *                      const envP,
+                    int                               const flags,
+                    const char *                      const appname,
+                    const char *                      const appversion,
+                    const struct xmlrpc_clientparms * const clientparmsP,
+                    unsigned int                      const parmSize) {
+/*----------------------------------------------------------------------------
+   This function is not thread-safe.
+-----------------------------------------------------------------------------*/
+    if (globalClientExists)
+        xmlrpc_faultf(
+            envP,
+            "Xmlrpc-c global client instance has already been created "
+            "(need to call xmlrpc_client_cleanup() before you can "
+            "reinitialize).");
+    else {
+        /* The following call is not thread-safe */
+        xmlrpc_client_setup_global_const(envP);
+        if (!envP->fault_occurred) {
+            xmlrpc_client_create(envP, flags, appname, appversion,
+                                 clientparmsP, parmSize, &globalClientP);
+            if (!envP->fault_occurred)
+                globalClientExists = true;
+
+            if (envP->fault_occurred)
+                xmlrpc_client_teardown_global_const();
+        }
+    }
+}
+
+
+
+void
+xmlrpc_client_init(int          const flags,
+                   const char * const appname,
+                   const char * const appversion) {
+/*----------------------------------------------------------------------------
+   This function is not thread-safe.
+-----------------------------------------------------------------------------*/
+    struct xmlrpc_clientparms clientparms;
+
+    /* As our interface does not allow for failure, we just fail silently ! */
+    
+    xmlrpc_env env;
+    xmlrpc_env_init(&env);
+
+    clientparms.transport = NULL;
+
+    /* The following call is not thread-safe */
+    xmlrpc_client_init2(&env, flags,
+                        appname, appversion,
+                        &clientparms, XMLRPC_CPSIZE(transport));
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void 
+xmlrpc_client_cleanup() {
+/*----------------------------------------------------------------------------
+   This function is not thread-safe
+-----------------------------------------------------------------------------*/
+    XMLRPC_ASSERT(globalClientExists);
+
+    xmlrpc_client_destroy(globalClientP);
+
+    globalClientExists = false;
+
+    /* The following call is not thread-safe */
+    xmlrpc_client_teardown_global_const();
+}
+
+
+
+static void
+validateGlobalClientExists(xmlrpc_env * const envP) {
+
+    if (!globalClientExists)
+        xmlrpc_faultf(envP,
+                      "Xmlrpc-c global client instance "
+                      "has not been created "
+                      "(need to call xmlrpc_client_init2()).");
+}
+
+
+
+void
+xmlrpc_client_transport_call(
+    xmlrpc_env *               const envP,
+    void *                     const reserved ATTR_UNUSED, 
+        /* for client handle */
+    const xmlrpc_server_info * const serverP,
+    xmlrpc_mem_block *         const callXmlP,
+    xmlrpc_mem_block **        const respXmlPP) {
+
+    validateGlobalClientExists(envP);
+    if (!envP->fault_occurred)
+        xmlrpc_client_transport_call2(envP, globalClientP, serverP,
+                                      callXmlP, respXmlPP);
+}
+
+
+
+static void
+clientCall_va(xmlrpc_env *               const envP,
+              const xmlrpc_server_info * const serverInfoP,
+              const char *               const methodName,
+              const char *               const format,
+              va_list                          args,
+              xmlrpc_value **            const resultPP) {
+
+    validateGlobalClientExists(envP);
+    if (!envP->fault_occurred) {
+        xmlrpc_value * paramArrayP;
+        const char * suffix;
+        
+        xmlrpc_build_value_va(envP, format, args, &paramArrayP, &suffix);
+        
+        if (!envP->fault_occurred) {
+            if (*suffix != '\0')
+                xmlrpc_faultf(envP, "Junk after the argument "
+                              "specifier: '%s'.  "
+                              "There must be exactly one arument.",
+                              suffix);
+            else
+                xmlrpc_client_call2(envP, globalClientP, serverInfoP,
+                                    methodName, paramArrayP, resultPP);
+            
+            xmlrpc_DECREF(paramArrayP);
+        }
+    }
+}
+
+
+
+xmlrpc_value * 
+xmlrpc_client_call(xmlrpc_env * const envP,
+                   const char * const serverUrl,
+                   const char * const methodName,
+                   const char * const format,
+                   ...) {
+
+    xmlrpc_value * resultP;
+    
+    xmlrpc_server_info * serverInfoP;
+
+    serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+        
+    if (!envP->fault_occurred) {
+        va_list args;
+        va_start(args, format);
+    
+        clientCall_va(envP, serverInfoP, methodName, format, args, &resultP);
+
+        va_end(args);
+        xmlrpc_server_info_free(serverInfoP);
+    }
+    
+    return resultP;
+}
+
+
+
+xmlrpc_value * 
+xmlrpc_client_call_server(xmlrpc_env *               const envP,
+                          const xmlrpc_server_info * const serverP,
+                          const char *               const methodName,
+                          const char *               const format, 
+                          ...) {
+
+    va_list args;
+    xmlrpc_value * resultP;
+
+    va_start(args, format);
+    clientCall_va(envP, serverP, methodName, format, args, &resultP);
+    va_end(args);
+
+    return resultP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_client_call_server_params(
+    xmlrpc_env *               const envP,
+    const xmlrpc_server_info * const serverInfoP,
+    const char *               const methodName,
+    xmlrpc_value *             const paramArrayP) {
+
+    xmlrpc_value * resultP;
+
+    validateGlobalClientExists(envP);
+
+    if (!envP->fault_occurred)
+        xmlrpc_client_call2(envP, globalClientP,
+                            serverInfoP, methodName, paramArrayP,
+                            &resultP);
+
+    return resultP;
+}
+
+
+
+xmlrpc_value * 
+xmlrpc_client_call_params(xmlrpc_env *   const envP,
+                          const char *   const serverUrl,
+                          const char *   const methodName,
+                          xmlrpc_value * const paramArrayP) {
+
+    xmlrpc_value * resultP;
+
+    validateGlobalClientExists(envP);
+
+    if (!envP->fault_occurred) {
+        xmlrpc_server_info * serverInfoP;
+
+        serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+        
+        if (!envP->fault_occurred) {
+            xmlrpc_client_call2(envP, globalClientP,
+                                serverInfoP, methodName, paramArrayP,
+                                &resultP);
+            
+            xmlrpc_server_info_free(serverInfoP);
+        }
+    }
+    return resultP;
+}                            
+
+
+
+void 
+xmlrpc_client_call_server_asynch_params(
+    xmlrpc_server_info * const serverInfoP,
+    const char *         const methodName,
+    xmlrpc_response_handler    responseHandler,
+    void *               const userData,
+    xmlrpc_value *       const paramArrayP) {
+
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    validateGlobalClientExists(&env);
+
+    if (!env.fault_occurred)
+        xmlrpc_client_start_rpc(&env, globalClientP,
+                                serverInfoP, methodName, paramArrayP,
+                                responseHandler, userData);
+
+    if (env.fault_occurred) {
+        /* Unfortunately, we have no way to return an error and the
+           regular callback for a failed RPC is designed to have the
+           parameter array passed to it.  This was probably an oversight
+           of the original asynch design, but now we have to be as
+           backward compatible as possible, so we do this:
+        */
+        (*responseHandler)(serverInfoP->_server_url,
+                           methodName, paramArrayP, userData,
+                           &env, NULL);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void 
+xmlrpc_client_call_asynch(const char * const serverUrl,
+                          const char * const methodName,
+                          xmlrpc_response_handler responseHandler,
+                          void *       const userData,
+                          const char * const format,
+                          ...) {
+
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    validateGlobalClientExists(&env);
+
+    if (!env.fault_occurred) {
+        xmlrpc_value * paramArrayP;
+        const char * suffix;
+        va_list args;
+    
+        va_start(args, format);
+        xmlrpc_build_value_va(&env, format, args, &paramArrayP, &suffix);
+        va_end(args);
+    
+        if (!env.fault_occurred) {
+            if (*suffix != '\0')
+                xmlrpc_faultf(&env, "Junk after the argument "
+                              "specifier: '%s'.  "
+                              "There must be exactly one arument.",
+                              suffix);
+            else
+                xmlrpc_client_call_asynch_params(
+                    serverUrl, methodName, responseHandler, userData,
+                    paramArrayP);
+        }
+    }
+    if (env.fault_occurred)
+        (*responseHandler)(serverUrl, methodName, NULL, userData, &env, NULL);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_client_call_asynch_params(const char *   const serverUrl,
+                                 const char *   const methodName,
+                                 xmlrpc_response_handler responseHandler,
+                                 void *         const userData,
+                                 xmlrpc_value * const paramArrayP) {
+    xmlrpc_env env;
+    xmlrpc_server_info * serverInfoP;
+
+    xmlrpc_env_init(&env);
+
+    serverInfoP = xmlrpc_server_info_new(&env, serverUrl);
+
+    if (!env.fault_occurred) {
+        xmlrpc_client_call_server_asynch_params(
+            serverInfoP, methodName, responseHandler, userData, paramArrayP);
+        
+        xmlrpc_server_info_free(serverInfoP);
+    }
+    if (env.fault_occurred)
+        (*responseHandler)(serverUrl, methodName, paramArrayP, userData,
+                           &env, NULL);
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void 
+xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverInfoP,
+                                 const char *         const methodName,
+                                 xmlrpc_response_handler    responseHandler,
+                                 void *               const userData,
+                                 const char *         const format,
+                                 ...) {
+
+    xmlrpc_env env;
+    xmlrpc_value * paramArrayP;
+    const char * suffix;
+    va_list args;
+    
+    xmlrpc_env_init(&env);
+
+    va_start(args, format);
+    xmlrpc_build_value_va(&env, format, args, &paramArrayP, &suffix);
+    va_end(args);
+
+    if (!env.fault_occurred) {
+        if (*suffix != '\0')
+            xmlrpc_faultf(&env, "Junk after the argument "
+                          "specifier: '%s'.  "
+                          "There must be exactly one arument.",
+                          suffix);
+        else
+            xmlrpc_client_call_server_asynch_params(
+                serverInfoP, methodName, responseHandler, userData,
+                paramArrayP);
+
+        xmlrpc_DECREF(paramArrayP);
+    }
+    if (env.fault_occurred)
+        (*responseHandler)(serverInfoP->_server_url, methodName, NULL,
+                           userData, &env, NULL);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void 
+xmlrpc_client_event_loop_finish_asynch(void) {
+
+    XMLRPC_ASSERT(globalClientExists);
+    xmlrpc_client_event_loop_finish(globalClientP);
+}
+
+
+
+void 
+xmlrpc_client_event_loop_finish_asynch_timeout(
+    unsigned long const milliseconds) {
+
+    XMLRPC_ASSERT(globalClientExists);
+    xmlrpc_client_event_loop_finish_timeout(globalClientP, milliseconds);
+}
diff --git a/src/xmlrpc_data.c b/src/xmlrpc_data.c
new file mode 100644 (file)
index 0000000..15889b7
--- /dev/null
@@ -0,0 +1,852 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "bool.h"
+#include "mallocvar.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+
+
+
+static void
+destroyValue(xmlrpc_value * const valueP) {
+
+    /* First, we need to destroy this value's contents, if any. */
+    switch (valueP->_type) {
+    case XMLRPC_TYPE_INT:
+        break;
+        
+    case XMLRPC_TYPE_BOOL:
+        break;
+
+    case XMLRPC_TYPE_DOUBLE:
+        break;
+
+    case XMLRPC_TYPE_DATETIME:
+        xmlrpc_mem_block_clean(&valueP->_block);
+        break;
+
+    case XMLRPC_TYPE_STRING:
+        if (valueP->_wcs_block)
+            xmlrpc_mem_block_free(valueP->_wcs_block);
+        xmlrpc_mem_block_clean(&valueP->_block);
+        break;
+        
+    case XMLRPC_TYPE_BASE64:
+        xmlrpc_mem_block_clean(&valueP->_block);
+        break;
+
+    case XMLRPC_TYPE_ARRAY:
+        xmlrpc_destroyArrayContents(valueP);
+        break;
+        
+    case XMLRPC_TYPE_STRUCT:
+        xmlrpc_destroyStruct(valueP);
+        break;
+
+    case XMLRPC_TYPE_C_PTR:
+        break;
+
+    case XMLRPC_TYPE_NIL:
+        break;
+
+    case XMLRPC_TYPE_DEAD:
+        XMLRPC_ASSERT(false); /* Can't happen, per entry conditions */
+
+    default:
+        XMLRPC_ASSERT(false); /* There are no other possible values */
+    }
+
+    /* Next, we mark this value as invalid, to help catch refcount
+        ** errors. */
+    valueP->_type = XMLRPC_TYPE_DEAD;
+
+    /* Finally, we destroy the value itself. */
+    free(valueP);
+}
+
+
+
+/*=========================================================================
+**  Reference Counting
+**=========================================================================
+**  Some simple reference-counting code. The xmlrpc_DECREF routine is in
+**  charge of destroying values when their reference count equals zero.
+*/
+
+void 
+xmlrpc_INCREF (xmlrpc_value * const valueP) {
+
+    XMLRPC_ASSERT_VALUE_OK(valueP);
+    XMLRPC_ASSERT(valueP->_refcount > 0);
+    
+    ++valueP->_refcount;
+}
+
+
+
+void 
+xmlrpc_DECREF (xmlrpc_value * const valueP) {
+
+    XMLRPC_ASSERT_VALUE_OK(valueP);
+    XMLRPC_ASSERT(valueP->_refcount > 0);
+    XMLRPC_ASSERT(valueP->_type != XMLRPC_TYPE_DEAD);
+
+    valueP->_refcount--;
+
+    /* If we have no more refs, we need to deallocate this value. */
+    if (valueP->_refcount == 0)
+        destroyValue(valueP);
+}
+
+
+
+/*=========================================================================
+    Utiltiies
+=========================================================================*/
+
+const char *
+xmlrpc_typeName(xmlrpc_type const type) {
+
+    switch(type) {
+
+    case XMLRPC_TYPE_INT:      return "INT";
+    case XMLRPC_TYPE_BOOL:     return "BOOL";
+    case XMLRPC_TYPE_DOUBLE:   return "DOUBLE";
+    case XMLRPC_TYPE_DATETIME: return "DATETIME";
+    case XMLRPC_TYPE_STRING:   return "STRING";
+    case XMLRPC_TYPE_BASE64:   return "BASE64";
+    case XMLRPC_TYPE_ARRAY:    return "ARRAY";
+    case XMLRPC_TYPE_STRUCT:   return "STRUCT";
+    case XMLRPC_TYPE_C_PTR:    return "C_PTR";
+    case XMLRPC_TYPE_NIL:      return "NIL";
+    case XMLRPC_TYPE_DEAD:     return "DEAD";
+    default:                   return "???";
+    }
+}
+
+
+
+static void
+verifyNoNulls(xmlrpc_env * const envP,
+              const char * const contents,
+              unsigned int const len) {
+/*----------------------------------------------------------------------------
+   Verify that the character array 'contents', which is 'len' bytes long,
+   does not contain any NUL characters, which means it can be made into
+   a passable ASCIIZ string just by adding a terminating NUL.
+
+   Fail if the array contains a NUL.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+
+    for (i = 0; i < len && !envP->fault_occurred; i++)
+        if (contents[i] == '\0')
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_TYPE_ERROR, 
+                "String must not contain NUL characters");
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+
+static void
+verifyNoNullsW(xmlrpc_env *    const envP,
+               const wchar_t * const contents,
+               unsigned int    const len) {
+/*----------------------------------------------------------------------------
+   Same as verifyNoNulls(), but for wide characters.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+
+    for (i = 0; i < len && !envP->fault_occurred; i++)
+        if (contents[i] == '\0')
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_TYPE_ERROR, 
+                "String must not contain NUL characters");
+}
+#endif
+
+
+
+static void
+validateType(xmlrpc_env *         const envP,
+             const xmlrpc_value * const valueP,
+             xmlrpc_type          const expectedType) {
+
+    if (valueP->_type != expectedType) {
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where "
+            "type %s was expected.", 
+            xmlrpc_typeName(valueP->_type), xmlrpc_typeName(expectedType));
+    }
+}
+
+
+
+/*=========================================================================
+    Extracting XML-RPC value
+===========================================================================
+  These routines extract XML-RPC values into ordinary C data types.
+
+  For array and struct values, see the separates files xmlrpc_array.c
+  and xmlrpc_struct.c.
+=========================================================================*/
+
+void 
+xmlrpc_read_int(xmlrpc_env *         const envP,
+                const xmlrpc_value * const valueP,
+                xmlrpc_int32 *       const intValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_INT);
+    if (!envP->fault_occurred)
+        *intValueP = valueP->_value.i;
+}
+
+
+
+void
+xmlrpc_read_bool(xmlrpc_env *         const envP,
+                 const xmlrpc_value * const valueP,
+                 xmlrpc_bool *        const boolValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_BOOL);
+    if (!envP->fault_occurred)
+        *boolValueP = valueP->_value.b;
+}
+
+
+
+void
+xmlrpc_read_double(xmlrpc_env *         const envP,
+                   const xmlrpc_value * const valueP,
+                   xmlrpc_double *      const doubleValueP) {
+    
+    validateType(envP, valueP, XMLRPC_TYPE_DOUBLE);
+    if (!envP->fault_occurred)
+        *doubleValueP = valueP->_value.d;
+
+}
+
+
+/* datetime stuff is in xmlrpc_datetime.c */
+
+static void
+accessStringValue(xmlrpc_env *         const envP,
+                  const xmlrpc_value * const valueP,
+                  size_t *             const lengthP,
+                  const char **        const contentsP) {
+    
+    validateType(envP, valueP, XMLRPC_TYPE_STRING);
+    if (!envP->fault_occurred) {
+        unsigned int const size = 
+            XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
+        const char * const contents = 
+            XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+        unsigned int const len = size - 1;
+            /* The memblock has a null character added to the end */
+
+        verifyNoNulls(envP, contents, len);
+
+        *lengthP = len;
+        *contentsP = contents;
+    }
+}
+             
+
+
+void
+xmlrpc_read_string(xmlrpc_env *         const envP,
+                   const xmlrpc_value * const valueP,
+                   const char **        const stringValueP) {
+/*----------------------------------------------------------------------------
+   Read the value of an XML-RPC string as an ASCIIZ string.
+
+   Return the string in newly malloc'ed storage that Caller must free.
+
+   Fail if the string contains null characters (which means it wasn't
+   really a string, but XML-RPC doesn't seem to understand what a string
+   is, and such values are possible).
+-----------------------------------------------------------------------------*/
+    size_t length;
+    const char * contents;
+
+    accessStringValue(envP, valueP, &length, &contents);
+
+    if (!envP->fault_occurred) {
+        char * stringValue;
+            
+        stringValue = malloc(length+1);
+        if (stringValue == NULL)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate space "
+                "for %u-character string", length);
+        else {
+            memcpy(stringValue, contents, length);
+            stringValue[length] = '\0';
+
+            *stringValueP = stringValue;
+        }
+    }
+}
+
+
+
+void
+xmlrpc_read_string_old(xmlrpc_env *         const envP,
+                       const xmlrpc_value * const valueP,
+                       const char **        const stringValueP) {
+
+    size_t length;
+    accessStringValue(envP, valueP, &length, stringValueP);
+}
+
+
+
+void
+xmlrpc_read_string_lp(xmlrpc_env *         const envP,
+                      const xmlrpc_value * const valueP,
+                      size_t *             const lengthP,
+                      const char **        const stringValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_STRING);
+    if (!envP->fault_occurred) {
+        unsigned int const size = 
+            XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
+        const char * const contents = 
+            XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+
+        char * stringValue;
+
+        stringValue = malloc(size);
+        if (stringValue == NULL)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes "
+                "for string.", size);
+        else {
+            memcpy(stringValue, contents, size);
+            *stringValueP = stringValue;
+            *lengthP = size - 1;  /* Size includes terminating NUL */
+        }
+    }
+}
+
+
+
+void
+xmlrpc_read_string_lp_old(xmlrpc_env *         const envP,
+                          const xmlrpc_value * const valueP,
+                          size_t *             const lengthP,
+                          const char **        const stringValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_STRING);
+    if (!envP->fault_occurred) {
+        *lengthP =      XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
+        *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+    }
+}
+
+
+
+static __inline__ void
+setupWcsBlock(xmlrpc_env *   const envP,
+              xmlrpc_value * const valueP) {
+/*----------------------------------------------------------------------------
+   Add a wcs block (wchar_t string) to the indicated xmlrpc_value if it
+   doesn't have one already.
+-----------------------------------------------------------------------------*/
+    if (!valueP->_wcs_block) {
+        char * const contents = 
+            XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+        size_t const len = 
+            XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
+        valueP->_wcs_block = 
+            xmlrpc_utf8_to_wcs(envP, contents, len + 1);
+    }
+}
+
+
+
+#if HAVE_UNICODE_WCHAR
+
+static void
+accessStringValueW(xmlrpc_env *     const envP,
+                   xmlrpc_value *   const valueP,
+                   size_t *         const lengthP,
+                   const wchar_t ** const stringValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_STRING);
+    if (!envP->fault_occurred) {
+        setupWcsBlock(envP, valueP);
+
+        if (!envP->fault_occurred) {
+            wchar_t * const wcontents = 
+                XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
+            size_t const len = 
+                XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block) - 1;
+            
+            verifyNoNullsW(envP, wcontents, len);
+
+            *lengthP = len;
+            *stringValueP = wcontents;
+        }
+    }
+}
+
+
+              
+void
+xmlrpc_read_string_w(xmlrpc_env *     const envP,
+                     xmlrpc_value *   const valueP,
+                     const wchar_t ** const stringValueP) {
+
+    size_t length;
+    const wchar_t * wcontents;
+    
+    accessStringValueW(envP, valueP, &length, &wcontents);
+
+    if (!envP->fault_occurred) {
+        wchar_t * stringValue;
+        stringValue = malloc((length + 1) * sizeof(wchar_t));
+        if (stringValue == NULL)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR, 
+                "Unable to allocate space for %u-byte string", 
+                length);
+        else {
+            memcpy(stringValue, wcontents, length * sizeof(wchar_t));
+            stringValue[length] = '\0';
+            
+            *stringValueP = stringValue;
+        }
+    }
+}
+
+
+
+void
+xmlrpc_read_string_w_old(xmlrpc_env *     const envP,
+                         xmlrpc_value *   const valueP,
+                         const wchar_t ** const stringValueP) {
+
+    size_t length;
+
+    accessStringValueW(envP, valueP, &length, stringValueP);
+}
+
+
+
+void
+xmlrpc_read_string_w_lp(xmlrpc_env *     const envP,
+                        xmlrpc_value *   const valueP,
+                        size_t *         const lengthP,
+                        const wchar_t ** const stringValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_STRING);
+    if (!envP->fault_occurred) {
+        setupWcsBlock(envP, valueP);
+
+        if (!envP->fault_occurred) {
+            wchar_t * const wcontents = 
+                XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
+            size_t const size = 
+                XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
+
+            wchar_t * stringValue;
+            
+            stringValue = malloc(size * sizeof(wchar_t));
+            if (stringValue == NULL)
+                xmlrpc_env_set_fault_formatted(
+                    envP, XMLRPC_INTERNAL_ERROR, 
+                    "Unable to allocate space for %u-byte string", 
+                    size);
+            else {
+                memcpy(stringValue, wcontents, size * sizeof(wchar_t));
+                
+                *lengthP      = size - 1; /* size includes terminating NUL */
+                *stringValueP = stringValue;
+            }
+        }
+    }
+}
+
+
+
+void
+xmlrpc_read_string_w_lp_old(xmlrpc_env *     const envP,
+                            xmlrpc_value *   const valueP,
+                            size_t *         const lengthP,
+                            const wchar_t ** const stringValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_STRING);
+    if (!envP->fault_occurred) {
+        setupWcsBlock(envP, valueP);
+
+        if (!envP->fault_occurred) {
+            wchar_t * const wcontents = 
+                XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
+            size_t const size = 
+                XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
+            
+            *lengthP      = size - 1;  /* size includes terminatnig NUL */
+            *stringValueP = wcontents;
+        }
+    }
+}
+#endif
+
+
+
+void
+xmlrpc_read_base64(xmlrpc_env *           const envP,
+                   const xmlrpc_value *   const valueP,
+                   size_t *               const lengthP,
+                   const unsigned char ** const byteStringValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_BASE64);
+    if (!envP->fault_occurred) {
+        size_t const size = 
+            XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
+        const char * const contents = 
+            XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+
+        char * byteStringValue;
+
+        byteStringValue = malloc(size);
+        if (byteStringValue == NULL)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes "
+                "for byte string.", size);
+        else {
+            memcpy(byteStringValue, contents, size);
+            *byteStringValueP = (const unsigned char *)byteStringValue;
+            *lengthP = size;
+        }
+    }
+}
+
+
+
+void
+xmlrpc_read_base64_old(xmlrpc_env *           const envP,
+                       const xmlrpc_value *   const valueP,
+                       size_t *               const lengthP,
+                       const unsigned char ** const byteStringValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_BASE64);
+    if (!envP->fault_occurred) {
+        *lengthP =
+            XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
+        *byteStringValueP = (const unsigned char *)
+            XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+    }
+}
+
+
+
+void
+xmlrpc_read_base64_size(xmlrpc_env *           const envP,
+                        const xmlrpc_value *   const valueP,
+                        size_t *               const lengthP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_BASE64);
+    if (!envP->fault_occurred)
+        *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
+}
+
+
+
+void
+xmlrpc_read_nil(xmlrpc_env *   const envP,
+                xmlrpc_value * const valueP) {
+/*----------------------------------------------------------------------------
+   Read out the value of a nil value.  It doesn't have one, of course, so
+   this is essentially a no-op.  But it does validate the type and is
+   necessary to match all the other types.
+-----------------------------------------------------------------------------*/
+    validateType(envP, valueP, XMLRPC_TYPE_NIL);
+}
+
+
+
+void
+xmlrpc_read_cptr(xmlrpc_env *         const envP,
+                 const xmlrpc_value * const valueP,
+                 void **              const ptrValueP) {
+
+    validateType(envP, valueP, XMLRPC_TYPE_C_PTR);
+    if (!envP->fault_occurred)
+        *ptrValueP = valueP->_value.c_ptr;
+}
+
+
+
+xmlrpc_type xmlrpc_value_type (xmlrpc_value* value)
+{
+    XMLRPC_ASSERT_VALUE_OK(value);
+    return value->_type;
+}
+
+
+
+void
+xmlrpc_createXmlrpcValue(xmlrpc_env *    const envP,
+                         xmlrpc_value ** const valPP) {
+/*----------------------------------------------------------------------------
+   Create a blank xmlrpc_value to be filled in.
+
+   Set the reference count to 1.
+-----------------------------------------------------------------------------*/
+    xmlrpc_value * valP;
+
+    MALLOCVAR(valP);
+    if (!valP)
+        xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
+                             "Could not allocate memory for xmlrpc_value");
+    else
+        valP->_refcount = 1;
+
+    *valPP = valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_int_new(xmlrpc_env * const envP, 
+               xmlrpc_int32 const value) {
+
+    xmlrpc_value * valP;
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        valP->_type    = XMLRPC_TYPE_INT;
+        valP->_value.i = value;
+    }
+    return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_bool_new(xmlrpc_env * const envP, 
+                xmlrpc_bool  const value) {
+
+    xmlrpc_value * valP;
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        valP->_type = XMLRPC_TYPE_BOOL;
+        valP->_value.b = value;
+    }
+    return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_double_new(xmlrpc_env * const envP, 
+                  double       const value) {
+
+    xmlrpc_value * valP;
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        valP->_type = XMLRPC_TYPE_DOUBLE;
+        valP->_value.d = value;
+    }
+    return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_new_lp(xmlrpc_env * const envP, 
+                     size_t       const length,
+                     const char * const value) {
+
+    xmlrpc_value * valP;
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        valP->_type = XMLRPC_TYPE_STRING;
+        valP->_wcs_block = NULL;
+        XMLRPC_MEMBLOCK_INIT(char, envP, &valP->_block, length + 1);
+        if (!envP->fault_occurred) {
+            char * const contents =
+                XMLRPC_MEMBLOCK_CONTENTS(char, &valP->_block);
+            memcpy(contents, value, length);
+            contents[length] = '\0';
+        }
+        if (envP->fault_occurred)
+            free(valP);
+    }
+    return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_new(xmlrpc_env * const envP,
+                  const char * const value) {
+
+    return xmlrpc_string_new_lp(envP, strlen(value), value);
+}
+
+
+#if HAVE_UNICODE_WCHAR
+xmlrpc_value *
+xmlrpc_string_w_new_lp(xmlrpc_env *    const envP, 
+                       size_t          const length,
+                       const wchar_t * const value) {
+
+    xmlrpc_value * valP;
+
+    /* Initialize our XML-RPC value. */
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        valP->_type = XMLRPC_TYPE_STRING;
+
+        /* Build our wchar_t block first. */
+        valP->_wcs_block =
+            XMLRPC_MEMBLOCK_NEW(wchar_t, envP, length + 1);
+        if (!envP->fault_occurred) {
+            wchar_t * const wcs_contents =
+                XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valP->_wcs_block);
+
+            xmlrpc_mem_block * utf8P;
+
+            memcpy(wcs_contents, value, length * sizeof(wchar_t));
+            wcs_contents[length] = '\0';
+    
+            /* Convert the wcs block to UTF-8. */
+            utf8P = xmlrpc_wcs_to_utf8(envP, wcs_contents, length + 1);
+            if (!envP->fault_occurred) {
+                char * const utf8_contents =
+                    XMLRPC_MEMBLOCK_CONTENTS(char, utf8P);
+                size_t const utf8_len = XMLRPC_MEMBLOCK_SIZE(char, utf8P);
+
+                /* XXX - We need an extra memcopy to initialize _block. */
+                XMLRPC_MEMBLOCK_INIT(char, envP, &valP->_block, utf8_len);
+                if (!envP->fault_occurred) {
+                    char * contents;
+                    contents = XMLRPC_MEMBLOCK_CONTENTS(char, &valP->_block);
+                    memcpy(contents, utf8_contents, utf8_len);
+                }
+                XMLRPC_MEMBLOCK_FREE(char, utf8P);
+            }
+            if (envP->fault_occurred)
+                XMLRPC_MEMBLOCK_FREE(wchar_t, valP->_wcs_block);
+        }
+        if (envP->fault_occurred)
+            free(valP);
+    }
+    return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_string_w_new(xmlrpc_env *    const envP,
+                    const wchar_t * const value) {
+    return xmlrpc_string_w_new_lp(envP, wcslen(value), value);
+}
+#endif
+
+xmlrpc_value *
+xmlrpc_base64_new(xmlrpc_env *          const envP, 
+                  size_t                const length,
+                  const unsigned char * const value) {
+
+    xmlrpc_value * valP;
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        valP->_type = XMLRPC_TYPE_BASE64;
+
+        xmlrpc_mem_block_init(envP, &valP->_block, length);
+        if (!envP->fault_occurred) {
+            char * const contents = 
+                xmlrpc_mem_block_contents(&valP->_block);
+            memcpy(contents, value, length);
+        }
+        if (envP->fault_occurred)
+            free(valP);
+    }
+    return valP;
+}
+
+
+
+/* array stuff is in xmlrpc_array.c */
+
+
+
+xmlrpc_value *
+xmlrpc_cptr_new(xmlrpc_env *    const envP,
+                void *          const value) {
+
+    xmlrpc_value * valP;
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        valP->_type = XMLRPC_TYPE_C_PTR;
+        valP->_value.c_ptr = value;
+    }
+    return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_nil_new(xmlrpc_env *    const envP) {
+    xmlrpc_value * valP;
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+    if (!envP->fault_occurred)
+        valP->_type = XMLRPC_TYPE_NIL;
+
+    return valP;
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2001 by Eric Kidd. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/src/xmlrpc_datetime.c b/src/xmlrpc_datetime.c
new file mode 100644 (file)
index 0000000..bd190d2
--- /dev/null
@@ -0,0 +1,480 @@
+#include "xmlrpc_config.h"
+
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "bool.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+
+
+/* Future work: the XMLRPC_TYPE_DATETIME xmlrpc_value should store the
+   datetime as something computation-friendly, not as a string.  The
+   XML-RPC XML parser should parse the string value and reject the XML if
+   it isn't valid.
+
+   But this file should remain the authority on datetimes, so the XML
+   parser and builder should call on routines in here to do that.
+
+   time_t won't work because it can't represent times before 1970 or
+   after 2038.  We need to figure out something better.
+*/
+
+
+#ifdef WIN32
+
+static const bool win32 = TRUE;
+static const __int64 SECS_BETWEEN_EPOCHS = 11644473600;
+static const __int64 SECS_TO_100NS = 10000000; /* 10^7 */
+
+
+void UnixTimeToFileTime(const time_t t, LPFILETIME pft)
+{
+    // Note that LONGLONG is a 64-bit value
+    LONGLONG ll;
+    ll = Int32x32To64(t, SECS_TO_100NS) + SECS_BETWEEN_EPOCHS * SECS_TO_100NS;
+    pft->dwLowDateTime = (DWORD)ll;
+    pft->dwHighDateTime = ll >> 32;
+}
+
+void UnixTimeToSystemTime(const time_t t, LPSYSTEMTIME pst)
+{
+    FILETIME ft;
+
+    UnixTimeToFileTime(t, &ft);
+    FileTimeToSystemTime(&ft, pst);
+}
+
+static void UnixTimeFromFileTime(xmlrpc_env *  const envP, LPFILETIME pft, time_t * const timeValueP) 
+{ 
+    LONGLONG ll;
+
+    ll = ((LONGLONG)pft->dwHighDateTime << 32) + pft->dwLowDateTime;
+    /* convert to the Unix epoch */
+    ll -= (SECS_BETWEEN_EPOCHS * SECS_TO_100NS);
+    /* now convert to seconds */
+    ll /= SECS_TO_100NS; 
+
+    if ( (time_t)ll != ll )
+    {
+        //fail - value is too big for a time_t
+        xmlrpc_faultf(envP, "Does not indicate a valid date");
+        *timeValueP = (time_t)-1;
+        return;
+    }
+    *timeValueP = (time_t)ll;
+}
+
+static void UnixTimeFromSystemTime(xmlrpc_env *  const envP, LPSYSTEMTIME pst, time_t * const timeValueP) 
+{
+    FILETIME filetime;
+
+    SystemTimeToFileTime(pst, &filetime); 
+    UnixTimeFromFileTime(envP, &filetime, timeValueP); 
+}
+
+#else
+static const bool win32 = false;
+#endif
+
+
+static void
+validateDatetimeType(xmlrpc_env *         const envP,
+                     const xmlrpc_value * const valueP) {
+
+    if (valueP->_type != XMLRPC_TYPE_DATETIME) {
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where "
+            "type %s was expected.", 
+            xmlrpc_typeName(valueP->_type), 
+            xmlrpc_typeName(XMLRPC_TYPE_DATETIME));
+    }
+}
+
+
+
+void
+xmlrpc_read_datetime_str(xmlrpc_env *         const envP,
+                         const xmlrpc_value * const valueP,
+                         const char **        const stringValueP) {
+    
+    validateDatetimeType(envP, valueP);
+    if (!envP->fault_occurred) {
+        const char * const contents = 
+            XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+        *stringValueP = strdup(contents);
+        if (*stringValueP == NULL)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate space "
+                "for datetime string");
+    }
+}
+
+
+
+void
+xmlrpc_read_datetime_str_old(xmlrpc_env *         const envP,
+                             const xmlrpc_value * const valueP,
+                             const char **        const stringValueP) {
+    
+    validateDatetimeType(envP, valueP);
+    if (!envP->fault_occurred) {
+        *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
+    }
+}
+
+
+
+static void
+parseDateNumbers(const char * const t,
+                 unsigned int * const YP,
+                 unsigned int * const MP,
+                 unsigned int * const DP,
+                 unsigned int * const hP,
+                 unsigned int * const mP,
+                 unsigned int * const sP) {
+
+    char year[4+1];
+    char month[2+1];
+    char day[2+1];
+    char hour[2+1];
+    char minute[2+1];
+    char second[2+1];
+
+    assert(strlen(t) == 17);
+
+    year[0]   = t[ 0];
+    year[1]   = t[ 1];
+    year[2]   = t[ 2];
+    year[3]   = t[ 3];
+    year[4]   = '\0';
+
+    month[0]  = t[ 4];
+    month[1]  = t[ 5];
+    month[2]  = '\0';
+
+    day[0]    = t[ 6];
+    day[1]    = t[ 7];
+    day[2]    = '\0';
+
+    assert(t[ 8] == 'T');
+
+    hour[0]   = t[ 9];
+    hour[1]   = t[10];
+    hour[2]   = '\0';
+
+    assert(t[11] == ':');
+
+    minute[0] = t[12];
+    minute[1] = t[13];
+    minute[2] = '\0';
+
+    assert(t[14] == ':');
+
+    second[0] = t[15];
+    second[1] = t[16];
+    second[2] = '\0';
+
+    *YP = atoi(year);
+    *MP = atoi(month);
+    *DP = atoi(day);
+    *hP = atoi(hour);
+    *mP = atoi(minute);
+    *sP = atoi(second);
+}
+
+
+#ifdef HAVE_SETENV
+xmlrpc_bool const haveSetenv = true;
+#else
+xmlrpc_bool const haveSetenv = false;
+static void
+setenv(const char * const name ATTR_UNUSED,
+       const char * const value ATTR_UNUSED,
+       int          const replace ATTR_UNUSED) {
+    assert(FALSE);
+}
+#endif
+
+static void
+makeTimezoneUtc(xmlrpc_env *  const envP,
+                const char ** const oldTzP) {
+
+    const char * const tz = getenv("TZ");
+
+#ifdef WIN32
+       /* Windows implementation does not exist */
+       assert(TRUE);
+#endif
+
+    if (haveSetenv) {
+        if (tz) {
+            *oldTzP = strdup(tz);
+            if (*oldTzP == NULL)
+                xmlrpc_faultf(envP, "Unable to get memory to save TZ "
+                              "environment variable.");
+        } else
+            *oldTzP = NULL;
+
+        if (!envP->fault_occurred)
+            setenv("TZ", "", 1);
+    } else {
+        if (tz && strlen(tz) == 0) {
+            /* Everything's fine.  Nothing to change or restore */
+        } else {
+            /* Note that putenv() is not sufficient.  You can't restore
+               the original value with that, because it sets a pointer into
+               your own storage.
+            */
+            xmlrpc_faultf(envP, "Your TZ environment variable is not a "
+                          "null string and your C library does not have "
+                          "setenv(), so we can't change it.");
+        }
+    }
+}
+    
+
+
+static void
+restoreTimezone(const char * const oldTz) {
+
+    if (haveSetenv) {
+        setenv("TZ", oldTz, 1);
+        free((char*)oldTz);
+    }
+}
+
+
+
+static void
+mkAbsTimeWin32(xmlrpc_env * const envP ATTR_UNUSED,
+               struct tm    const brokenTime ATTR_UNUSED,
+               time_t     * const timeValueP ATTR_UNUSED) {
+#ifdef WIN32
+    /* Windows Implementation */
+    SYSTEMTIME stbrokenTime;
+
+    stbrokenTime.wHour = brokenTime.tm_hour;
+    stbrokenTime.wMinute = brokenTime.tm_min;
+    stbrokenTime.wSecond = brokenTime.tm_sec;
+    stbrokenTime.wMonth = brokenTime.tm_mon;
+    stbrokenTime.wDay = brokenTime.tm_mday;
+    stbrokenTime.wYear = brokenTime.tm_year;
+    stbrokenTime.wMilliseconds = 0;
+
+    /* When the date string is parsed into the tm structure, it was
+       modified to decrement the month count by one and convert the
+       4 digit year to a two digit year.  We undo what the parser 
+       did to make it a true SYSTEMTIME structure, then convert this
+       structure into a UNIX time_t structure
+    */
+    stbrokenTime.wYear+=1900;
+    stbrokenTime.wMonth+=1;
+
+    UnixTimeFromSystemTime(envP, &stbrokenTime,timeValueP);
+#endif
+}
+
+
+static void
+mkAbsTimeUnix(xmlrpc_env * const envP ATTR_UNUSED,
+              struct tm    const brokenTime ATTR_UNUSED,
+              time_t     * const timeValueP ATTR_UNUSED) {
+
+#ifndef WIN32
+    time_t mktimeResult;
+    const char * oldTz;
+    struct tm mktimeWork;
+
+    /* We use mktime() to create the time_t because it's the
+       best we have available, but mktime() takes a local time
+       argument, and we have absolute time.  So we fake it out
+       by temporarily setting the timezone to UTC.
+    */
+    makeTimezoneUtc(envP, &oldTz);
+
+    if (!envP->fault_occurred) {
+        mktimeWork = brokenTime;
+        mktimeResult = mktime(&mktimeWork);
+
+        restoreTimezone(oldTz);
+
+        if (mktimeResult == (time_t)-1)
+            xmlrpc_faultf(envP, "Does not indicate a valid date");
+        else
+            *timeValueP = mktimeResult;
+    }
+#endif
+}
+
+
+static void
+mkAbsTime(xmlrpc_env * const envP,
+          struct tm    const brokenTime,
+          time_t     * const timeValueP) {
+
+    if (win32)
+        mkAbsTimeWin32(envP, brokenTime, timeValueP);
+    else
+        mkAbsTimeUnix(envP, brokenTime, timeValueP);
+}
+
+
+
+static void
+validateFormat(xmlrpc_env * const envP,
+               const char * const t) {
+
+    if (strlen(t) != 17)
+        xmlrpc_faultf(envP, "%u characters instead of 15.", strlen(t));
+    else if (t[8] != 'T')
+        xmlrpc_faultf(envP, "9th character is '%c', not 'T'", t[8]);
+    else {
+        unsigned int i;
+
+        for (i = 0; i < 8 && !envP->fault_occurred; ++i)
+            if (!isdigit(t[i]))
+                xmlrpc_faultf(envP, "Not a digit: '%c'", t[i]);
+
+        if (!isdigit(t[9]))
+            xmlrpc_faultf(envP, "Not a digit: '%c'", t[9]);
+        if (!isdigit(t[10]))
+            xmlrpc_faultf(envP, "Not a digit: '%c'", t[10]);
+        if (t[11] != ':')
+            xmlrpc_faultf(envP, "Not a colon: '%c'", t[11]);
+        if (!isdigit(t[12]))
+            xmlrpc_faultf(envP, "Not a digit: '%c'", t[12]);
+        if (!isdigit(t[13]))
+            xmlrpc_faultf(envP, "Not a digit: '%c'", t[13]);
+        if (t[14] != ':')
+            xmlrpc_faultf(envP, "Not a colon: '%c'", t[14]);
+        if (!isdigit(t[15]))
+            xmlrpc_faultf(envP, "Not a digit: '%c'", t[15]);
+        if (!isdigit(t[16]))
+            xmlrpc_faultf(envP, "Not a digit: '%c'", t[16]);
+    }
+}        
+
+
+
+static void
+parseDatetime(xmlrpc_env * const envP,
+              const char * const t,
+              time_t *     const timeValueP) {
+/*----------------------------------------------------------------------------
+   Parse a time in the format stored in an xmlrpc_value and return the
+   time that it represents.
+
+   t[] is the input time string.  We return the result as *timeValueP.
+
+   Example of the format we parse: "19980717T14:08:55"
+   Note that this is not quite ISO 8601.  It's a bizarre combination of
+   two ISO 8601 formats.
+-----------------------------------------------------------------------------*/
+    validateFormat(envP, t);
+
+    if (!envP->fault_occurred) {
+        unsigned int Y, M, D, h, m, s;
+        
+        parseDateNumbers(t, &Y, &M, &D, &h, &m, &s);
+        
+        if (Y < 1900)
+            xmlrpc_faultf(envP, "Year is too early to represent as "
+                          "a standard Unix time");
+        else {
+            struct tm brokenTime;
+            
+            brokenTime.tm_sec   = s;
+            brokenTime.tm_min   = m;
+            brokenTime.tm_hour  = h;
+            brokenTime.tm_mday  = D;
+            brokenTime.tm_mon   = M - 1;
+            brokenTime.tm_year  = Y - 1900;
+            
+            mkAbsTime(envP, brokenTime, timeValueP);
+        }
+    }
+}
+
+
+
+void
+xmlrpc_read_datetime_sec(xmlrpc_env *         const envP,
+                         const xmlrpc_value * const valueP,
+                         time_t *             const timeValueP) {
+    
+    validateDatetimeType(envP, valueP);
+    if (!envP->fault_occurred)
+        parseDatetime(envP,
+                      XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block),
+                      timeValueP);
+}
+
+
+
+xmlrpc_value *
+xmlrpc_datetime_new_str(xmlrpc_env * const envP, 
+                        const char * const value) {
+
+    xmlrpc_value * valP;
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        valP->_type = XMLRPC_TYPE_DATETIME;
+
+        XMLRPC_TYPED_MEM_BLOCK_INIT(
+            char, envP, &valP->_block, strlen(value) + 1);
+        if (!envP->fault_occurred) {
+            char * const contents =
+                XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block);
+            strcpy(contents, value);
+        }
+        if (envP->fault_occurred)
+            free(valP);
+    }
+    return valP;
+}
+
+
+
+xmlrpc_value *
+xmlrpc_datetime_new_sec(xmlrpc_env * const envP, 
+                        time_t       const value) {
+
+    xmlrpc_value * valP;
+    
+    xmlrpc_createXmlrpcValue(envP, &valP);
+
+    if (!envP->fault_occurred) {
+        struct tm brokenTime;
+        char timeString[64];
+        
+        valP->_type = XMLRPC_TYPE_DATETIME;
+
+        gmtime_r(&value, &brokenTime);
+        
+        /* Note that this format is NOT ISO 8601 -- it's a bizarre
+           hybrid of two ISO 8601 formats.
+        */
+        strftime(timeString, sizeof(timeString), "%Y%m%dT%H:%M:%S", 
+                 &brokenTime);
+        
+        XMLRPC_TYPED_MEM_BLOCK_INIT(
+            char, envP, &valP->_block, strlen(timeString) + 1);
+        if (!envP->fault_occurred) {
+            char * const contents =
+                XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP->_block);
+            
+            strcpy(contents, timeString);
+        }
+        if (envP->fault_occurred)
+            free(valP);
+    }
+    return valP;
+}
diff --git a/src/xmlrpc_expat.c b/src/xmlrpc_expat.c
new file mode 100644 (file)
index 0000000..b08a35a
--- /dev/null
@@ -0,0 +1,480 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xmlparse.h> /* Expat */
+
+#include "bool.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/xmlparser.h"
+
+/* Define the contents of our internal structure. */
+struct _xml_element {
+    struct _xml_element *_parent;
+    char *_name;
+    xmlrpc_mem_block _cdata;    /* char */
+    xmlrpc_mem_block _children; /* xml_element* */
+};
+
+/* Check that we're using expat in UTF-8 mode, not wchar_t mode.
+** If you need to use expat in wchar_t mode, write a subroutine to
+** copy a wchar_t string to a char string & return an error for
+** any non-ASCII characters. Then call this subroutine on all
+** XML_Char strings passed to our event handlers before using the
+** data. */
+/* #if sizeof(char) != sizeof(XML_Char)
+** #error expat must define XML_Char to be a regular char. 
+** #endif
+*/
+
+#define XMLRPC_ASSERT_ELEM_OK(elem) \
+    XMLRPC_ASSERT((elem) != NULL && (elem)->_name != XMLRPC_BAD_POINTER)
+
+
+/*=========================================================================
+**  xml_element_new
+**=========================================================================
+**  Create a new xml_element. This routine isn't exported, because the
+**  arguments are implementation-dependent.
+*/
+
+static xml_element *
+xml_element_new (xmlrpc_env * const env,
+                 const char * const name) {
+
+    xml_element *retval;
+    int name_valid, cdata_valid, children_valid;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT(name != NULL);
+
+    /* Set up our error-handling preconditions. */
+    retval = NULL;
+    name_valid = cdata_valid = children_valid = 0;
+
+    /* Allocate our xml_element structure. */
+    retval = (xml_element*) malloc(sizeof(xml_element));
+    XMLRPC_FAIL_IF_NULL(retval, env, XMLRPC_INTERNAL_ERROR,
+                        "Couldn't allocate memory for XML element");
+
+    /* Set our parent field to NULL. */
+    retval->_parent = NULL;
+    
+    /* Copy over the element name. */
+    retval->_name = (char*) malloc(strlen(name) + 1);
+    XMLRPC_FAIL_IF_NULL(retval->_name, env, XMLRPC_INTERNAL_ERROR,
+                        "Couldn't allocate memory for XML element");
+    name_valid = 1;
+    strcpy(retval->_name, name);
+
+    /* Initialize a block to hold our CDATA. */
+    XMLRPC_TYPED_MEM_BLOCK_INIT(char, env, &retval->_cdata, 0);
+    XMLRPC_FAIL_IF_FAULT(env);
+    cdata_valid = 1;
+
+    /* Initialize a block to hold our child elements. */
+    XMLRPC_TYPED_MEM_BLOCK_INIT(xml_element*, env, &retval->_children, 0);
+    XMLRPC_FAIL_IF_FAULT(env);
+    children_valid = 1;
+
+ cleanup:
+    if (env->fault_occurred) {
+        if (retval) {
+            if (name_valid)
+                free(retval->_name);
+            if (cdata_valid)
+                xmlrpc_mem_block_clean(&retval->_cdata);
+            if (children_valid)
+                xmlrpc_mem_block_clean(&retval->_children);
+            free(retval);
+        }
+        return NULL;
+    } else {
+        return retval;
+    }
+}
+
+
+/*=========================================================================
+**  xml_element_free
+**=========================================================================
+**  Blow away an existing element & all of its child elements.
+*/
+void
+xml_element_free(xml_element * const elem) {
+
+    xmlrpc_mem_block *children;
+    int size, i;
+    xml_element **contents;
+
+    XMLRPC_ASSERT_ELEM_OK(elem);
+
+    free(elem->_name);
+    elem->_name = XMLRPC_BAD_POINTER;
+    xmlrpc_mem_block_clean(&elem->_cdata);
+
+    /* Deallocate all of our children recursively. */
+    children = &elem->_children;
+    contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, children);
+    size = XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, children);
+    for (i = 0; i < size; i++)
+        xml_element_free(contents[i]);
+
+    xmlrpc_mem_block_clean(&elem->_children);
+    free(elem);
+}
+
+
+/*=========================================================================
+**  Miscellaneous Accessors
+**=========================================================================
+**  Return the fields of the xml_element. See the header for more
+**  documentation on each function works.
+*/
+
+
+
+const char *
+xml_element_name(const xml_element * const elemP) {
+
+    XMLRPC_ASSERT_ELEM_OK(elemP);
+    return elemP->_name;
+}
+
+
+
+/* The result of this function is NOT VALID until the end_element handler
+** has been called! */
+size_t xml_element_cdata_size (xml_element *elem)
+{
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    return XMLRPC_TYPED_MEM_BLOCK_SIZE(char, &elem->_cdata) - 1;
+}
+
+char *xml_element_cdata (xml_element *elem)
+{
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &elem->_cdata);
+}
+
+
+
+size_t
+xml_element_children_size(const xml_element * const elemP) {
+    XMLRPC_ASSERT_ELEM_OK(elemP);
+    return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element *, &elemP->_children);
+}
+
+
+
+xml_element **
+xml_element_children(const xml_element * const elemP) {
+    XMLRPC_ASSERT_ELEM_OK(elemP);
+    return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element *, &elemP->_children);
+}
+
+
+
+/*=========================================================================
+**  Internal xml_element Utility Functions
+**=========================================================================
+*/
+
+static void xml_element_append_cdata (xmlrpc_env *env,
+                                      xml_element *elem,
+                                      char *cdata,
+                                      size_t size)
+{
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_ELEM_OK(elem);    
+
+    XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, &elem->_cdata, cdata, size);
+}
+
+/* Whether or not this function succeeds, it takes ownership of the 'child'
+** argument.
+** WARNING - This is the exact opposite of the usual memory ownership
+** rules for xmlrpc_value! So please pay attention. */
+static void xml_element_append_child (xmlrpc_env *env,
+                                      xml_element *elem,
+                                      xml_element *child)
+{
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    XMLRPC_ASSERT_ELEM_OK(child);
+    XMLRPC_ASSERT(child->_parent == NULL);
+
+    XMLRPC_TYPED_MEM_BLOCK_APPEND(xml_element*, env, &elem->_children,
+                                  &child, 1);
+    if (!env->fault_occurred)
+        child->_parent = elem;
+    else
+        xml_element_free(child);
+}
+
+
+/*=========================================================================
+**  Our parse context. We pass this around as expat user data.
+**=========================================================================
+*/
+
+typedef struct {
+    xmlrpc_env env;
+    xml_element * rootP;
+    xml_element * currentP;
+} parseContext;
+
+
+/*=========================================================================
+**  Expat Event Handler Functions
+**=========================================================================
+*/
+
+static void
+startElement(void *      const userData,
+             XML_Char *  const name,
+             XML_Char ** const atts ATTR_UNUSED) {
+
+    parseContext * const contextP = userData;
+
+    XMLRPC_ASSERT(contextP != NULL);
+    XMLRPC_ASSERT(name != NULL);
+
+    if (!contextP->env.fault_occurred) {
+        xml_element * elemP;
+
+        elemP = xml_element_new(&contextP->env, name);
+        if (!contextP->env.fault_occurred) {
+            XMLRPC_ASSERT(elemP != NULL);
+
+            /* Insert the new element in the appropriate place. */
+            if (!contextP->rootP) {
+                /* No root yet, so this element must be the root. */
+                contextP->rootP = elemP;
+                contextP->currentP = elemP;
+            } else {
+                XMLRPC_ASSERT(contextP->currentP != NULL);
+
+                /* (We need to watch our error handling invariants
+                   very carefully here. Read the docs for
+                   xml_element_append_child.
+                */
+                xml_element_append_child(&contextP->env, contextP->currentP,
+                                         elemP);
+                if (!contextP->env.fault_occurred)
+                    contextP->currentP = elemP;
+            }
+            if (contextP->env.fault_occurred)
+                xml_element_free(elemP);
+        }
+        if (contextP->env.fault_occurred) {
+            /* Having changed *contextP to reflect failure, we are responsible
+               for undoing everything that has been done so far in this
+               context.
+            */
+            if (contextP->rootP)
+                xml_element_free(contextP->rootP);
+        }
+    }
+}
+
+
+
+static void
+endElement(void *     const userData,
+           XML_Char * const name ATTR_UNUSED) {
+
+    parseContext * const contextP = userData;
+
+    XMLRPC_ASSERT(contextP != NULL);
+    XMLRPC_ASSERT(name != NULL);
+
+    if (!contextP->env.fault_occurred) {
+        /* I think Expat enforces these facts: */
+        XMLRPC_ASSERT(xmlrpc_streq(name, contextP->currentP->_name));
+        XMLRPC_ASSERT(contextP->currentP->_parent != NULL ||
+                      contextP->currentP == contextP->rootP);
+
+        /* Add a trailing NUL to our cdata. */
+        xml_element_append_cdata(&contextP->env, contextP->currentP, "\0", 1);
+        if (!contextP->env.fault_occurred)
+            /* Pop our "stack" of elements. */
+            contextP->currentP = contextP->currentP->_parent;
+
+        if (contextP->env.fault_occurred) {
+            /* Having changed *contextP to reflect failure, we are responsible
+               for undoing everything that has been done so far in this
+               context.
+            */
+            if (contextP->rootP)
+                xml_element_free(contextP->rootP);
+        }
+    }
+}
+
+
+
+static void
+characterData(void *     const userData,
+              XML_Char * const s,
+              int        const len) {
+
+    parseContext * const contextP = userData;
+
+    XMLRPC_ASSERT(contextP != NULL);
+    XMLRPC_ASSERT(s != NULL);
+    XMLRPC_ASSERT(len >= 0);
+
+    if (!contextP->env.fault_occurred) {
+        XMLRPC_ASSERT(contextP->currentP != NULL);
+    
+        xml_element_append_cdata(&contextP->env, contextP->currentP, s, len);
+    }
+}
+
+
+
+static void
+createParser(xmlrpc_env *   const envP,
+             parseContext * const contextP,
+             XML_Parser *   const parserP) {
+/*----------------------------------------------------------------------------
+   Create an Expat parser to parse our XML.
+-----------------------------------------------------------------------------*/
+    XML_Parser parser;
+
+    parser = xmlrpc_XML_ParserCreate(NULL);
+    if (parser == NULL)
+        xmlrpc_faultf(envP, "Could not create expat parser");
+    else {
+        /* Initialize our parse context. */
+        xmlrpc_env_init(&contextP->env);
+        contextP->rootP    = NULL;
+        contextP->currentP = NULL;
+
+        xmlrpc_XML_SetUserData(parser, contextP);
+        xmlrpc_XML_SetElementHandler(
+            parser,
+            (XML_StartElementHandler) startElement,
+            (XML_EndElementHandler) endElement);
+        xmlrpc_XML_SetCharacterDataHandler(
+            parser,
+            (XML_CharacterDataHandler) characterData);
+        
+        *parserP = parser;
+    }
+}
+
+
+
+static void
+destroyParser(XML_Parser     const parser,
+              parseContext * const contextP) {
+
+    xmlrpc_env_clean(&contextP->env);
+
+    xmlrpc_XML_ParserFree(parser);
+}
+
+
+
+void
+xml_parse(xmlrpc_env *   const envP,
+          const char *   const xmlData,
+          size_t         const xmlDataLen,
+          xml_element ** const resultPP) {
+/*----------------------------------------------------------------------------
+  Parse the XML text 'xmlData', of length 'xmlDataLen'.  Return the
+  description of the element that the XML text contains as *resultPP.
+-----------------------------------------------------------------------------*/
+    /* 
+       This is an Expat driver.
+   
+       We set up event-based parser handlers for Expat and set Expat loose
+       on the XML.  Expat walks through the XML, calling our handlers along
+       the way.  Our handlers build up the element description in our
+       'context' variable, so that when Expat is finished, our results are
+       in 'context' and we just have to pluck them out.
+
+       We should allow the user to specify the encoding in 'xmlData', but
+       we don't.
+    */
+    XML_Parser parser;
+    parseContext context;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(xmlData != NULL);
+
+    createParser(envP, &context, &parser);
+
+    if (!envP->fault_occurred) {
+        bool ok;
+
+        ok = xmlrpc_XML_Parse(parser, xmlData, xmlDataLen, 1);
+            /* sets 'context', *envP */
+        if (!ok) {
+            /* Expat failed on its own to parse it -- this is not an error
+               that our handlers detected.
+            */
+            xmlrpc_env_set_fault(
+                envP, XMLRPC_PARSE_ERROR,
+                xmlrpc_XML_ErrorString(xmlrpc_XML_GetErrorCode(parser)));
+            if (!context.env.fault_occurred) {
+                /* Have to clean up what our handlers built before Expat
+                   barfed.
+                */
+                if (context.rootP)
+                    xml_element_free(context.rootP);
+            }
+        } else {
+            /* Expat got through the XML OK, but when it called our handlers,
+               they might have detected a problem.  They would have noted
+               such a problem in *contextP.
+            */
+            if (context.env.fault_occurred)
+                xmlrpc_env_set_fault_formatted(
+                    envP, context.env.fault_code,
+                    "XML doesn't parse.  %s", context.env.fault_string);
+            else {
+                XMLRPC_ASSERT(context.rootP != NULL);
+                XMLRPC_ASSERT(context.currentP == NULL);
+                
+                *resultPP = context.rootP;
+            }
+        }
+        destroyParser(parser, &context);
+    }
+}
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/src/xmlrpc_libxml2.c b/src/xmlrpc_libxml2.c
new file mode 100644 (file)
index 0000000..9cba719
--- /dev/null
@@ -0,0 +1,427 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+** Copyright (C) 2002 Ximian, Inc.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#include <xmlparser.h>
+#else
+#include <libxml/parser.h>
+#endif
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/xmlparser.h"
+
+/* Define the contents of our internal structure. */
+struct _xml_element {
+    struct _xml_element *_parent;
+    char *_name;
+    xmlrpc_mem_block _cdata;    /* char */
+    xmlrpc_mem_block _children; /* xml_element* */
+};
+
+#define XMLRPC_ASSERT_ELEM_OK(elem) \
+    XMLRPC_ASSERT((elem) != NULL && (elem)->_name != XMLRPC_BAD_POINTER)
+
+
+/*=========================================================================
+**  xml_element_new
+**=========================================================================
+**  Create a new xml_element. This routine isn't exported, because the
+**  arguments are implementation-dependent.
+*/
+
+static xml_element *xml_element_new (xmlrpc_env *env, char *name)
+{
+    xml_element *retval;
+    int name_valid, cdata_valid, children_valid;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT(name != NULL);
+
+    /* Set up our error-handling preconditions. */
+    retval = NULL;
+    name_valid = cdata_valid = children_valid = 0;
+
+    /* Allocate our xml_element structure. */
+    retval = (xml_element*) malloc(sizeof(xml_element));
+    XMLRPC_FAIL_IF_NULL(retval, env, XMLRPC_INTERNAL_ERROR,
+                       "Couldn't allocate memory for XML element");
+
+    /* Set our parent field to NULL. */
+    retval->_parent = NULL;
+    
+    /* Copy over the element name. */
+    retval->_name = (char*) malloc(strlen(name) + 1);
+    XMLRPC_FAIL_IF_NULL(retval->_name, env, XMLRPC_INTERNAL_ERROR,
+                       "Couldn't allocate memory for XML element");
+    name_valid = 1;
+    strcpy(retval->_name, name);
+
+    /* Initialize a block to hold our CDATA. */
+    XMLRPC_TYPED_MEM_BLOCK_INIT(char, env, &retval->_cdata, 0);
+    XMLRPC_FAIL_IF_FAULT(env);
+    cdata_valid = 1;
+
+    /* Initialize a block to hold our child elements. */
+    XMLRPC_TYPED_MEM_BLOCK_INIT(xml_element*, env, &retval->_children, 0);
+    XMLRPC_FAIL_IF_FAULT(env);
+    children_valid = 1;
+
+ cleanup:
+    if (env->fault_occurred) {
+       if (retval) {
+           if (name_valid)
+               free(retval->_name);
+           if (cdata_valid)
+               xmlrpc_mem_block_clean(&retval->_cdata);
+           if (children_valid)
+               xmlrpc_mem_block_clean(&retval->_children);
+           free(retval);
+       }
+       return NULL;
+    } else {
+       return retval;
+    }
+}
+
+
+/*=========================================================================
+**  xml_element_free
+**=========================================================================
+**  Blow away an existing element & all of its child elements.
+*/
+
+void xml_element_free (xml_element *elem)
+{
+    xmlrpc_mem_block *children;
+    int size, i;
+    xml_element **contents;
+
+    XMLRPC_ASSERT_ELEM_OK(elem);
+
+    free(elem->_name);
+    elem->_name = XMLRPC_BAD_POINTER;
+    xmlrpc_mem_block_clean(&elem->_cdata);
+
+    /* Deallocate all of our children recursively. */
+    children = &elem->_children;
+    contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, children);
+    size = XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, children);
+    for (i = 0; i < size; i++)
+       xml_element_free(contents[i]);
+
+    xmlrpc_mem_block_clean(&elem->_children);
+    free(elem);
+}
+
+
+/*=========================================================================
+**  Miscellaneous Accessors
+**=========================================================================
+**  Return the fields of the xml_element. See the header for more
+**  documentation on each function works.
+*/
+
+const char *xml_element_name (const xml_element * const elem)
+{
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    return elem->_name;
+}
+
+/* The result of this function is NOT VALID until the end_element handler
+** has been called! */
+size_t xml_element_cdata_size (xml_element *elem)
+{
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    return XMLRPC_TYPED_MEM_BLOCK_SIZE(char, &elem->_cdata) - 1;
+}
+
+char *xml_element_cdata (xml_element *elem)
+{
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &elem->_cdata);
+}
+
+size_t xml_element_children_size (const xml_element *const elem)
+{
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    return XMLRPC_TYPED_MEM_BLOCK_SIZE(xml_element*, &elem->_children);
+}
+
+xml_element **xml_element_children (const xml_element *const elem)
+{
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    return XMLRPC_TYPED_MEM_BLOCK_CONTENTS(xml_element*, &elem->_children);
+}
+
+
+/*=========================================================================
+**  Internal xml_element Utility Functions
+**=========================================================================
+*/
+
+static void xml_element_append_cdata (xmlrpc_env *env,
+                                     xml_element *elem,
+                                     char *cdata,
+                                     size_t size)
+{
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_ELEM_OK(elem);    
+
+    XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, &elem->_cdata, cdata, size);
+}
+
+/* Whether or not this function succeeds, it takes ownership of the 'child'
+** argument.
+** WARNING - This is the exact opposite of the usual memory ownership
+** rules for xmlrpc_value! So please pay attention. */
+static void xml_element_append_child (xmlrpc_env *env,
+                                     xml_element *elem,
+                                     xml_element *child)
+{
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_ELEM_OK(elem);
+    XMLRPC_ASSERT_ELEM_OK(child);
+    XMLRPC_ASSERT(child->_parent == NULL);
+
+    XMLRPC_TYPED_MEM_BLOCK_APPEND(xml_element*, env, &elem->_children,
+                                  &child, 1);
+    if (!env->fault_occurred)
+       child->_parent = elem;
+    else
+        xml_element_free(child);
+}
+
+
+/*=========================================================================
+**  Our parse context. We pass this around as libxml user data.
+**=========================================================================
+*/
+
+typedef struct {
+    xmlrpc_env *env;
+    xml_element *root;
+    xml_element *current;
+} parse_context;
+
+
+/*=========================================================================
+**  LibXML Event Handler Functions
+**=========================================================================
+*/
+
+static void
+start_element (void *user_data, const xmlChar *name, const xmlChar **attrs)
+{
+    parse_context *context;
+    xml_element *elem, *new_current;
+
+    XMLRPC_ASSERT(user_data != NULL && name != NULL);
+
+    /* Get our context and see if an error has already occured. */
+    context = (parse_context*) user_data;
+    if (!context->env->fault_occurred) {
+
+       /* Set up our error-handling preconditions. */
+       elem = NULL;
+
+       /* Build a new element. */
+       elem = xml_element_new(context->env, (char *) name);
+       XMLRPC_FAIL_IF_FAULT(context->env);
+
+       /* Insert it in the appropriate place. */
+       if (!context->root) {
+           context->root = elem;
+           context->current = elem;
+           elem = NULL;
+       } else {
+           XMLRPC_ASSERT(context->current != NULL);
+
+           /* (We need to watch our error handling invariants very carefully
+           ** here. Read the docs for xml_element_append_child. */
+           new_current = elem;
+           xml_element_append_child(context->env, context->current, elem);
+           elem = NULL;
+           XMLRPC_FAIL_IF_FAULT(context->env);
+           context->current = new_current;
+       }
+
+ cleanup:
+       if (elem)
+           xml_element_free(elem);
+    }
+}
+
+static void
+end_element (void *user_data, const xmlChar *name)
+{
+    parse_context *context;
+
+    XMLRPC_ASSERT(user_data != NULL && name != NULL);
+
+    /* Get our context and see if an error has already occured. */
+    context = (parse_context*) user_data;
+    if (!context->env->fault_occurred) {
+
+       /* XXX - I think expat enforces these facts, but I want to be sure.
+       ** If one of these assertion ever fails, it should be replaced by a
+       ** non-assertion runtime error check. */
+       XMLRPC_ASSERT(strcmp(name, context->current->_name) == 0);
+       XMLRPC_ASSERT(context->current->_parent != NULL ||
+                     context->current == context->root);
+
+       /* Add a trailing '\0' to our cdata. */
+       xml_element_append_cdata(context->env, context->current, "\0", 1);
+       XMLRPC_FAIL_IF_FAULT(context->env);     
+
+       /* Pop our "stack" of elements. */
+       context->current = context->current->_parent;
+
+ cleanup:
+       return;
+    }
+}
+
+static void character_data (void *user_data, const xmlChar *s, int len)
+{
+    parse_context *context;
+
+    XMLRPC_ASSERT(user_data != NULL && s != NULL && len >= 0);
+
+    /* Get our context and see if an error has already occured. */
+    context = (parse_context*) user_data;
+    if (!context->env->fault_occurred) {
+
+       XMLRPC_ASSERT(context->current != NULL);
+       
+       xml_element_append_cdata(context->env, context->current, (char *) s, len);
+       XMLRPC_FAIL_IF_FAULT(context->env);
+
+ cleanup:
+       return;
+    }
+}
+
+
+/*=========================================================================
+**  LibXML Driver
+**=========================================================================
+**  XXX - We should allow the user to specify the encoding of our xml_data.
+*/
+
+static xmlSAXHandler sax_handler = {
+    NULL,      /* internalSubset */
+    NULL,      /* isStandalone */
+    NULL,      /* hasInternalSubset */
+    NULL,      /* hasExternalSubset */
+    NULL,      /* resolveEntity */
+    NULL,      /* getEntity */
+    NULL,      /* entityDecl */
+    NULL,      /* notationDecl */
+    NULL,      /* attributeDecl */
+    NULL,      /* elementDecl */
+    NULL,      /* unparsedEntityDecl */
+    NULL,      /* setDocumentLocator */
+    NULL,      /* startDocument */
+    NULL,      /* endDocument */
+    start_element,       /* startElement */
+    end_element,         /* endElement */
+    NULL,      /* reference */
+    character_data,      /* characters */
+    NULL,      /* ignorableWhitespace */
+    NULL,      /* processingInstruction */
+    NULL,      /* comment */
+    NULL,      /* warning */
+    NULL,      /* error */
+    NULL,      /* fatalError */
+    NULL,      /* getParameterEntity */
+    NULL,      /* cdataBlock */
+    NULL,      /* externalSubset */
+    1          /* initialized */
+    
+    /* Following are SAX2 fields. Any ifdef here? */ 
+
+    ,NULL,     /* _private */
+    NULL,      /* startElementNs */
+    NULL,      /* endElementNs */
+    NULL       /* serror */
+};
+
+
+
+void
+xml_parse(xmlrpc_env *   const envP,
+          const char *   const xmlData,
+          size_t         const xmlDataLen,
+          xml_element ** const resultPP) {
+
+    parse_context context;
+    xmlParserCtxt *parser;
+    int err;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(xmlData != NULL && xmlDataLen >= 0);
+
+    /* Set up our error-handling preconditions. */
+    parser = NULL;
+    context.root = NULL;
+    
+    /* Set up the rest of our parse context. */
+    context.env     = envP;
+    context.current = NULL;
+
+    /* Set up our XML parser. */
+    parser = xmlCreatePushParserCtxt(&sax_handler, &context, NULL, 0, NULL);
+    XMLRPC_FAIL_IF_NULL(parser, envP, XMLRPC_INTERNAL_ERROR,
+                        "Could not create expat parser");
+
+    /* Parse our data. */
+    err = xmlParseChunk(parser, xmlData, xmlDataLen, 1);
+    if (err)
+        XMLRPC_FAIL(envP, XMLRPC_PARSE_ERROR, "XML parsing failed");
+    XMLRPC_FAIL_IF_FAULT(envP);
+
+    /* Perform some sanity checks. */
+    XMLRPC_ASSERT(context.root != NULL);
+    XMLRPC_ASSERT(context.current == NULL);
+
+    *resultPP = context.root;
+
+ cleanup:
+    if (parser)
+        xmlFreeParserCtxt(parser);
+
+    if (envP->fault_occurred) {
+        if (context.root)
+            xml_element_free(context.root);
+    }
+}
diff --git a/src/xmlrpc_parse.c b/src/xmlrpc_parse.c
new file mode 100644 (file)
index 0000000..3eb2ca8
--- /dev/null
@@ -0,0 +1,990 @@
+/* Copyright information is at end of file. */
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "bool.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/xmlparser.h"
+
+
+/*=========================================================================
+**  Data Format
+**=========================================================================
+**  An XML-RPC document consists of a single methodCall or methodResponse
+**  element.
+**
+**  methodCall     methodName, params
+**  methodResponse (params|fault)
+**  params         param*
+**  param          value
+**  fault          value
+**  value          (i4|int|boolean|string|double|dateTime.iso8601|base64|
+**                  nil|struct|array)
+**  array          data
+**  data           value*
+**  struct         member*
+**  member         name, value
+**
+**  Contain CDATA: methodName, i4, int, boolean, string, double,
+**                 dateTime.iso8601, base64, name
+**
+**  We attempt to validate the structure of the XML document carefully.
+**  We also try *very* hard to handle malicious data gracefully, and without
+**  leaking memory.
+**
+**  The CHECK_NAME and CHECK_CHILD_COUNT macros examine an XML element, and
+**  invoke XMLRPC_FAIL if something looks wrong.
+*/
+
+#define CHECK_NAME(env,elem,name) \
+    do \
+        if (!xmlrpc_streq((name), xml_element_name(elem))) \
+            XMLRPC_FAIL2(env, XMLRPC_PARSE_ERROR, \
+             "Expected element of type <%s>, found <%s>", \
+                         (name), xml_element_name(elem)); \
+    while (0)
+
+#define CHECK_CHILD_COUNT(env,elem,count) \
+    do \
+        if (xml_element_children_size(elem) != (count)) \
+            XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR, \
+             "Expected <%s> to have %d children, found %d", \
+                         xml_element_name(elem), (count), \
+                         xml_element_children_size(elem)); \
+    while (0)
+
+static xml_element *
+get_child_by_name (xmlrpc_env *env, xml_element *parent, char *name)
+{
+    size_t child_count, i;
+    xml_element **children;
+
+    children = xml_element_children(parent);
+    child_count = xml_element_children_size(parent);
+    for (i = 0; i < child_count; i++) {
+        if (xmlrpc_streq(xml_element_name(children[i]), name))
+            return children[i];
+    }
+    
+    xmlrpc_env_set_fault_formatted(env, XMLRPC_PARSE_ERROR,
+                                   "Expected <%s> to have child <%s>",
+                                   xml_element_name(parent), name);
+    return NULL;
+}
+
+
+/*=========================================================================
+**  Number-Parsing Functions
+**=========================================================================
+**  These functions mirror atoi, atof, etc., but provide better
+**  error-handling.  These routines may reset errno to zero.
+*/
+
+static xmlrpc_int32
+xmlrpc_atoi(xmlrpc_env *env, char *str, size_t strlen,
+            xmlrpc_int32 min, xmlrpc_int32 max)
+{
+    long i;
+    char *end;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_PTR_OK(str);
+
+    /* Suppress compiler warnings. */
+    i = 0;
+
+    /* Check for leading white space. */
+    if (isspace(str[0]))
+    XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
+                 "\"%s\" must not contain whitespace", str);
+
+    /* Convert the value. */
+    end = str + strlen;
+    errno = 0;
+    i = strtol(str, &end, 10);
+
+    /* Look for ERANGE. */
+    if (errno != 0)
+        /* XXX - Do all operating systems have thread-safe strerror? */
+        XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
+                     "error parsing \"%s\": %s (%d)",
+                     str, strerror(errno), errno);
+    
+    /* Look for out-of-range errors which didn't produce ERANGE. */
+    if (i < min || i > max)
+        XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
+                     "\"%s\" must be in range %d to %d", str, min, max);
+
+    /* Check for unused characters. */
+    if (end != str + strlen)
+        XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
+                     "\"%s\" contained trailing data", str);
+    
+ cleanup:
+    errno = 0;
+    if (env->fault_occurred)
+        return 0;
+    return (xmlrpc_int32) i;
+}
+
+
+
+static double
+xmlrpc_atod(xmlrpc_env *env, char *str, size_t strlen)
+{
+    double d;
+    char *end;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_PTR_OK(str);
+
+    /* Suppress compiler warnings. */
+    d = 0.0;
+
+    /* Check for leading white space. */
+    if (isspace(str[0]))
+        XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
+                     "\"%s\" must not contain whitespace", str);
+    
+    /* Convert the value. */
+    end = str + strlen;
+    errno = 0;
+    d = strtod(str, &end);
+    
+    /* Look for ERANGE. */
+    if (errno != 0)
+        /* XXX - Do all operating systems have thread-safe strerror? */
+        XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
+                     "error parsing \"%s\": %s (%d)",
+                     str, strerror(errno), errno);
+    
+    /* Check for unused characters. */
+    if (end != str + strlen)
+        XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
+                     "\"%s\" contained trailing data", str);
+
+ cleanup:
+    errno = 0;
+    if (env->fault_occurred)
+        return 0.0;
+    return d;
+}
+
+
+/*=========================================================================
+**  make_string
+**=========================================================================
+**  Make an XML-RPC string.
+**
+** SECURITY: We validate our UTF-8 first.  This incurs a performance
+** penalty, but ensures that we will never pass maliciously malformed
+** UTF-8 data back up to the user layer, where it could wreak untold
+** damange. Don't comment out this check unless you know *exactly* what
+** you're doing.  (Win32 developers who remove this check are *begging*
+** to wind up on BugTraq, because many of the Win32 filesystem routines
+** rely on an insecure UTF-8 decoder.)
+**
+** XXX - This validation is redundant if the user chooses to convert
+** UTF-8 data into a wchar_t string.
+*/
+
+static xmlrpc_value *
+make_string(xmlrpc_env * const envP,
+            char *       const cdata,
+            size_t       const cdata_size) {
+#if HAVE_UNICODE_WCHAR
+    xmlrpc_validate_utf8(envP, cdata, cdata_size);
+#endif
+
+    if (envP->fault_occurred)
+        return NULL;
+    return xmlrpc_build_value(envP, "s#", cdata, cdata_size);
+}
+
+
+
+/* Forward declaration for recursion */
+static xmlrpc_value *
+convert_value(xmlrpc_env *  const envP,
+              unsigned int  const maxRecursion,
+              xml_element * const elemP);
+
+
+
+static void
+convertBase64(xmlrpc_env *    const envP,
+              const char *    const cdata,
+              size_t          const cdata_size,
+              xmlrpc_value ** const valuePP) {
+    
+    xmlrpc_mem_block *decoded;
+    
+    decoded = xmlrpc_base64_decode(envP, cdata, cdata_size);
+    if (!envP->fault_occurred) {
+        unsigned char * const asciiData =
+            XMLRPC_MEMBLOCK_CONTENTS(unsigned char, decoded);
+        size_t const asciiLen =
+            XMLRPC_MEMBLOCK_SIZE(unsigned char, decoded);
+
+        *valuePP = xmlrpc_build_value(envP, "6", asciiData, asciiLen);
+        
+        XMLRPC_MEMBLOCK_FREE(unsigned char, decoded);
+    }
+}
+
+
+
+/*=========================================================================
+**  convert_array
+**=========================================================================
+**  Convert an XML element representing an array into an xmlrpc_value.
+*/
+
+static xmlrpc_value *
+convert_array(xmlrpc_env *  const envP,
+              unsigned int  const maxRecursion,
+              xml_element * const elemP) {
+
+    xml_element *data, **values, *value;
+    xmlrpc_value *array, *item;
+    int size, i;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(elemP != NULL);
+
+    /* Set up our error-handling preconditions. */
+    array = item = NULL;
+
+    /* Allocate an array to hold our values. */
+    array = xmlrpc_build_value(envP, "()");
+    XMLRPC_FAIL_IF_FAULT(envP);
+
+    /* We don't need to check our element name--our callers do that. */
+    CHECK_CHILD_COUNT(envP, elemP, 1);
+    data = xml_element_children(elemP)[0];
+    CHECK_NAME(envP, data, "data");
+    
+    /* Iterate over our children. */
+    values = xml_element_children(data);
+    size = xml_element_children_size(data);
+    for (i = 0; i < size; i++) {
+        value = values[i];
+        item = convert_value(envP, maxRecursion-1, value);
+        XMLRPC_FAIL_IF_FAULT(envP);
+
+        xmlrpc_array_append_item(envP, array, item);
+        xmlrpc_DECREF(item);
+        item = NULL;
+        XMLRPC_FAIL_IF_FAULT(envP);
+    }
+
+ cleanup:
+    if (item)
+        xmlrpc_DECREF(item);
+    if (envP->fault_occurred) {
+        if (array)
+            xmlrpc_DECREF(array);
+        return NULL;
+    }
+    return array;
+}
+
+
+
+/*=========================================================================
+**  convert_struct
+**=========================================================================
+**  Convert an XML element representing a struct into an xmlrpc_value.
+*/
+
+static xmlrpc_value *
+convert_struct(xmlrpc_env *  const envP,
+               unsigned int  const maxRecursion,
+               xml_element * const elemP) {
+
+    xmlrpc_value *strct, *key, *value;
+    xml_element **members, *member, *name_elemP, *value_elemP;
+    int size, i;
+    char *cdata;
+    size_t cdata_size;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(elemP != NULL);
+
+    /* Set up our error-handling preconditions. */
+    strct = key = value = NULL;
+
+    /* Allocate an array to hold our members. */
+    strct = xmlrpc_struct_new(envP);
+    XMLRPC_FAIL_IF_FAULT(envP);
+
+    /* Iterate over our children, extracting key/value pairs. */
+    /* We don't need to check our element name--our callers do that. */
+    members = xml_element_children(elemP);
+    size = xml_element_children_size(elemP);
+    for (i = 0; i < size; i++) {
+        member = members[i];
+        CHECK_NAME(envP, member, "member");
+        CHECK_CHILD_COUNT(envP, member, 2);
+
+        /* Get our key. */
+        name_elemP = get_child_by_name(envP, member, "name");
+        XMLRPC_FAIL_IF_FAULT(envP);
+        CHECK_CHILD_COUNT(envP, name_elemP, 0);
+        cdata = xml_element_cdata(name_elemP);
+        cdata_size = xml_element_cdata_size(name_elemP);
+        key = make_string(envP, cdata, cdata_size);
+        XMLRPC_FAIL_IF_FAULT(envP);
+
+        /* Get our value. */
+        value_elemP = get_child_by_name(envP, member, "value");
+        XMLRPC_FAIL_IF_FAULT(envP);
+        value = convert_value(envP, maxRecursion-1, value_elemP);
+        XMLRPC_FAIL_IF_FAULT(envP);
+
+        /* Add the key/value pair to our struct. */
+        xmlrpc_struct_set_value_v(envP, strct, key, value);
+        XMLRPC_FAIL_IF_FAULT(envP);
+
+        /* Release our references & memory, and restore our invariants. */
+        xmlrpc_DECREF(key);
+        key = NULL;
+        xmlrpc_DECREF(value);
+        value = NULL;
+    }
+    
+ cleanup:
+    if (key)
+        xmlrpc_DECREF(key);
+    if (value)
+        xmlrpc_DECREF(value);
+    if (envP->fault_occurred) {
+        if (strct)
+            xmlrpc_DECREF(strct);
+        return NULL;
+    }
+    return strct;
+}
+
+
+
+static xmlrpc_value *
+convert_value(xmlrpc_env *  const envP,
+              unsigned int  const maxRecursion,
+              xml_element * const elemP) {
+/*----------------------------------------------------------------------------
+   Compute the xmlrpc_value represented by the XML <value> element 'elem'.
+   Return that xmlrpc_value.
+
+   We call convert_array() and convert_struct(), which may ultimately
+   call us recursively.  Don't recurse any more than 'maxRecursion'
+   times.
+-----------------------------------------------------------------------------*/
+    int child_count;
+    xmlrpc_value * retval;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(elemP != NULL);
+
+    /* Error-handling preconditions.
+    ** If we haven't changed any of these from their default state, we're
+    ** allowed to tail-call xmlrpc_build_value. */
+    retval = NULL;
+
+    /* Assume we'll need to recurse, make sure we're allowed */
+    if (maxRecursion < 1) 
+        XMLRPC_FAIL(envP, XMLRPC_PARSE_ERROR,
+                    "Nested data structure too deep.");
+
+    /* Validate our structure, and see whether we have a child element. */
+    CHECK_NAME(envP, elemP, "value");
+    child_count = xml_element_children_size(elemP);
+
+    if (child_count == 0) {
+        /* We have no type element, so treat the value as a string. */
+        char * const cdata      = xml_element_cdata(elemP);
+        size_t const cdata_size = xml_element_cdata_size(elemP);
+        retval = make_string(envP, cdata, cdata_size);
+    } else {
+        /* We should have a type tag inside our value tag. */
+        xml_element * child;
+        const char * child_name;
+        
+        CHECK_CHILD_COUNT(envP, elemP, 1);
+        child = xml_element_children(elemP)[0];
+        
+        /* Parse our value-containing element. */
+        child_name = xml_element_name(child);
+        if (xmlrpc_streq(child_name, "struct")) {
+            retval = convert_struct(envP, maxRecursion, child);
+        } else if (xmlrpc_streq(child_name, "array")) {
+            CHECK_CHILD_COUNT(envP, child, 1);
+            retval = convert_array(envP, maxRecursion, child);
+        } else {
+            char * cdata;
+            size_t cdata_size;
+
+            CHECK_CHILD_COUNT(envP, child, 0);
+            cdata = xml_element_cdata(child);
+            cdata_size = xml_element_cdata_size(child);
+            if (xmlrpc_streq(child_name, "i4") ||
+                xmlrpc_streq(child_name, "int")) {
+                xmlrpc_int32 const i =
+                    xmlrpc_atoi(envP, cdata, strlen(cdata),
+                                XMLRPC_INT32_MIN, XMLRPC_INT32_MAX);
+                XMLRPC_FAIL_IF_FAULT(envP);
+                retval = xmlrpc_build_value(envP, "i", i);
+            } else if (xmlrpc_streq(child_name, "string")) {
+                retval = make_string(envP, cdata, cdata_size);
+            } else if (xmlrpc_streq(child_name, "boolean")) {
+                xmlrpc_int32 const i =
+                    xmlrpc_atoi(envP, cdata, strlen(cdata), 0, 1);
+                XMLRPC_FAIL_IF_FAULT(envP);
+                retval = xmlrpc_build_value(envP, "b", (xmlrpc_bool) i);
+            } else if (xmlrpc_streq(child_name, "double")) {
+                double const d = xmlrpc_atod(envP, cdata, strlen(cdata));
+                XMLRPC_FAIL_IF_FAULT(envP);
+                retval = xmlrpc_build_value(envP, "d", d);
+            } else if (xmlrpc_streq(child_name, "dateTime.iso8601")) {
+                retval = xmlrpc_build_value(envP, "8", cdata);
+            } else if (xmlrpc_streq(child_name, "nil")) {
+                retval = xmlrpc_build_value(envP, "n");
+            } else if (xmlrpc_streq(child_name, "base64")) {
+                /* No more tail calls once we do this! */
+
+                convertBase64(envP, cdata, cdata_size, &retval);
+                if (envP->fault_occurred)
+                    /* Just for cleanup code: */
+                    retval = NULL;
+            } else {
+                XMLRPC_FAIL1(envP, XMLRPC_PARSE_ERROR,
+                             "Unknown value type -- XML element is named "
+                             "<%s>", child_name);
+            }
+        }
+    }
+
+ cleanup:
+    if (envP->fault_occurred) {
+        if (retval)
+            xmlrpc_DECREF(retval);
+        retval = NULL;
+    }
+    return retval;
+}
+
+
+
+/*=========================================================================
+**  convert_params
+**=========================================================================
+**  Convert an XML element representing a list of params into an
+**  xmlrpc_value (of type array).
+*/
+
+static xmlrpc_value *
+convert_params(xmlrpc_env *        const envP,
+               const xml_element * const elemP) {
+/*----------------------------------------------------------------------------
+   Convert an XML element representing a list of parameters (i.e.  a
+   <params> element) to an xmlrpc_value of type array.  Note that an
+   array is normally represented in XML by a <value> element.  We use
+   type xmlrpc_value to represent the parameter list just for convenience.
+-----------------------------------------------------------------------------*/
+    xmlrpc_value *array, *item;
+    int size, i;
+    xml_element **params, *param, *value;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(elemP != NULL);
+
+    /* Set up our error-handling preconditions. */
+    array = item = NULL;
+
+    /* Allocate an array to hold our parameters. */
+    array = xmlrpc_build_value(envP, "()");
+    XMLRPC_FAIL_IF_FAULT(envP);
+
+    /* We're responsible for checking our own element name. */
+    CHECK_NAME(envP, elemP, "params");    
+
+    /* Iterate over our children. */
+    size = xml_element_children_size(elemP);
+    params = xml_element_children(elemP);
+    for (i = 0; i < size; ++i) {
+        unsigned int const maxNest = xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID);
+
+        param = params[i];
+        CHECK_NAME(envP, param, "param");
+        CHECK_CHILD_COUNT(envP, param, 1);
+
+        value = xml_element_children(param)[0];
+        item = convert_value(envP, maxNest, value);
+        XMLRPC_FAIL_IF_FAULT(envP);
+
+        xmlrpc_array_append_item(envP, array, item);
+        xmlrpc_DECREF(item);
+        item = NULL;
+        XMLRPC_FAIL_IF_FAULT(envP);
+    }
+
+ cleanup:
+    if (envP->fault_occurred) {
+        if (array)
+            xmlrpc_DECREF(array);
+        if (item)
+            xmlrpc_DECREF(item);
+        return NULL;
+    }
+    return array;
+}
+
+
+
+static void
+parseCallXml(xmlrpc_env *   const envP,
+             const char *   const xmlData,
+             size_t         const xmlLen,
+             xml_element ** const callElemPP) {
+
+    xml_element * callElemP;
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+    xml_parse(&env, xmlData, xmlLen, &callElemP);
+    if (env.fault_occurred)
+        xmlrpc_env_set_fault_formatted(
+            envP, env.fault_code, "Call is not valid XML.  %s",
+            env.fault_string);
+    else {
+        if (!xmlrpc_streq(xml_element_name(callElemP), "methodCall"))
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_PARSE_ERROR,
+                "XML-RPC call should be a <methodCall> element.  "
+                "Instead, we have a <%s> element.",
+                xml_element_name(callElemP));
+
+        if (!envP->fault_occurred)
+            *callElemPP = callElemP;
+
+        if (envP->fault_occurred)
+            xml_element_free(callElemP);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+parseMethodNameElement(xmlrpc_env *  const envP,
+                       xml_element * const nameElemP,
+                       const char ** const methodNameP) {
+    
+    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(nameElemP), "methodName"));
+
+    if (xml_element_children_size(nameElemP) > 0)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_PARSE_ERROR,
+            "A <methodName> element should not have children.  "
+            "This one has %u of them.", xml_element_children_size(nameElemP));
+    else {
+        const char * const cdata = xml_element_cdata(nameElemP);
+
+        xmlrpc_validate_utf8(envP, cdata, strlen(cdata));
+
+        if (!envP->fault_occurred) {
+            *methodNameP = strdup(cdata);
+            if (*methodNameP == NULL)
+                xmlrpc_faultf(envP,
+                              "Could not allocate memory for method name");
+        }
+    }
+}            
+
+
+
+static void
+parseCallChildren(xmlrpc_env *    const envP,
+                  xml_element *   const callElemP,
+                  const char **   const methodNameP,
+                  xmlrpc_value ** const paramArrayPP ) {
+/*----------------------------------------------------------------------------
+  Parse the children of a <methodCall> XML element *callElemP.  They should
+  be <methodName> and <params>.
+-----------------------------------------------------------------------------*/
+    size_t const callChildCount = xml_element_children_size(callElemP);
+
+    xml_element * nameElemP;
+        
+    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(callElemP), "methodCall"));
+    
+    nameElemP = get_child_by_name(envP, callElemP, "methodName");
+    
+    if (!envP->fault_occurred) {
+        parseMethodNameElement(envP, nameElemP, methodNameP);
+            
+        if (!envP->fault_occurred) {
+            /* Convert our parameters. */
+            if (callChildCount > 1) {
+                xml_element * paramsElemP;
+
+                paramsElemP = get_child_by_name(envP, callElemP, "params");
+                    
+                if (!envP->fault_occurred)
+                    *paramArrayPP = convert_params(envP, paramsElemP);
+            } else {
+                /* Workaround for Ruby XML-RPC and old versions of
+                   xmlrpc-epi.  Future improvement: Instead of looking
+                   at child count, we should just check for existence
+                   of <params>.
+                */
+                *paramArrayPP = xmlrpc_array_new(envP);
+            }
+            if (!envP->fault_occurred) {
+                if (callChildCount > 2)
+                    xmlrpc_env_set_fault_formatted(
+                        envP, XMLRPC_PARSE_ERROR,
+                        "<methodCall> has extraneous children, other than "
+                        "<methodName> and <params>.  Total child count = %u",
+                        callChildCount);
+                    
+                if (envP->fault_occurred)
+                    xmlrpc_DECREF(*paramArrayPP);
+            }
+            if (envP->fault_occurred)
+                xmlrpc_strfree(*methodNameP);
+        }
+    }
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_parse_call
+**=========================================================================
+**  Given some XML text, attempt to parse it as an XML-RPC call. Return
+**  a newly allocated xmlrpc_call structure (or NULL, if an error occurs).
+**  The two output variables will contain either valid values (which
+**  must free() and xmlrpc_DECREF(), respectively) or NULLs (if an error
+**  occurs).
+*/
+
+void 
+xmlrpc_parse_call(xmlrpc_env *    const envP,
+                  const char *    const xmlData,
+                  size_t          const xmlLen,
+                  const char **   const methodNameP,
+                  xmlrpc_value ** const paramArrayPP) {
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(xmlData != NULL);
+    XMLRPC_ASSERT(methodNameP != NULL && paramArrayPP != NULL);
+
+    /* SECURITY: Last-ditch attempt to make sure our content length is
+       legal.  XXX - This check occurs too late to prevent an attacker
+       from creating an enormous memory block, so you should try to
+       enforce it *before* reading any data off the network.
+     */
+    if (xmlLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_LIMIT_EXCEEDED_ERROR,
+            "XML-RPC request too large.  Max allowed is %u bytes",
+            xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID));
+    else {
+        xml_element * callElemP;
+        parseCallXml(envP, xmlData, xmlLen, &callElemP);
+        if (!envP->fault_occurred) {
+            parseCallChildren(envP, callElemP, methodNameP, paramArrayPP);
+
+            xml_element_free(callElemP);
+        }
+    }
+    if (envP->fault_occurred) {
+        *methodNameP  = NULL;
+        *paramArrayPP = NULL;
+    }
+}
+
+
+
+static void
+interpretFaultValue(xmlrpc_env *   const envP,
+                    xmlrpc_value * const faultVP,
+                    int *          const faultCodeP,
+                    const char **  const faultStringP) {
+                
+    if (faultVP->_type != XMLRPC_TYPE_STRUCT)
+        xmlrpc_env_set_fault(
+            envP, XMLRPC_PARSE_ERROR,
+            "<value> element of <fault> response contains is not "
+            "of structure type");
+    else {
+        xmlrpc_value * faultCodeVP;
+        xmlrpc_env fvEnv;
+
+        xmlrpc_env_init(&fvEnv);
+
+        xmlrpc_struct_read_value(&fvEnv, faultVP, "faultCode", &faultCodeVP);
+        if (!fvEnv.fault_occurred) {
+            xmlrpc_read_int(&fvEnv, faultCodeVP, faultCodeP);
+            if (!fvEnv.fault_occurred) {
+                xmlrpc_value * faultStringVP;
+
+                xmlrpc_struct_read_value(&fvEnv, faultVP, "faultString",
+                                         &faultStringVP);
+                if (!fvEnv.fault_occurred) {
+                    xmlrpc_read_string(&fvEnv, faultStringVP, faultStringP);
+                    xmlrpc_DECREF(faultStringVP);
+                }
+            }
+            xmlrpc_DECREF(faultCodeVP);
+        }
+        if (fvEnv.fault_occurred)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_PARSE_ERROR,
+                "Invalid struct for <fault> value.  %s", fvEnv.fault_string);
+
+        xmlrpc_env_clean(&fvEnv);
+    }
+}
+
+
+
+static void
+parseFaultElement(xmlrpc_env *        const envP,
+                  const xml_element * const faultElement,
+                  int *               const faultCodeP,
+                  const char **       const faultStringP) {
+                  
+    unsigned int const maxRecursion =
+        xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID);
+
+    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(faultElement), "fault"));
+
+    if (xml_element_children_size(faultElement) != 1)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_PARSE_ERROR,
+            "<fault> element should have 1 child, but it has %u.",
+            xml_element_children_size(faultElement));
+    else {
+        xml_element * const faultValueP =
+            xml_element_children(faultElement)[0];
+
+        xmlrpc_value * faultVP;
+
+        faultVP = convert_value(envP, maxRecursion, faultValueP);
+        
+        if (!envP->fault_occurred) {
+            interpretFaultValue(envP, faultVP, faultCodeP, faultStringP);
+
+            xmlrpc_DECREF(faultVP);
+        }
+    }
+}
+
+
+
+static void
+parseParamsElement(xmlrpc_env *        const envP,
+                   const xml_element * const paramsElementP,
+                   xmlrpc_value **     const resultPP) {
+
+    xmlrpc_value * paramsVP;
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(paramsElementP), "params"));
+
+    paramsVP = convert_params(envP, paramsElementP);
+
+    if (!envP->fault_occurred) {
+        int arraySize;
+        xmlrpc_env sizeEnv;
+
+        XMLRPC_ASSERT_ARRAY_OK(paramsVP);
+        
+        xmlrpc_env_init(&sizeEnv);
+
+        arraySize = xmlrpc_array_size(&sizeEnv, paramsVP);
+        /* Since it's a valid array, as asserted above, can't fail */
+        XMLRPC_ASSERT(!sizeEnv.fault_occurred);
+
+        if (arraySize != 1)
+            xmlrpc_env_set_fault_formatted(
+                &env, XMLRPC_PARSE_ERROR,
+                "Contains %d items.  It should have 1.",
+                arraySize);
+        else {
+            xmlrpc_array_read_item(envP, paramsVP, 0, resultPP);
+        }
+        xmlrpc_DECREF(paramsVP);
+        xmlrpc_env_clean(&sizeEnv);
+    }
+    if (env.fault_occurred)
+        xmlrpc_env_set_fault_formatted(
+            envP, env.fault_code,
+            "Invalid <params> element.  %s", env.fault_string);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+parseMethodResponseElt(xmlrpc_env *        const envP,
+                       const xml_element * const methodResponseEltP,
+                       xmlrpc_value **     const resultPP,
+                       int *               const faultCodeP,
+                       const char **       const faultStringP) {
+    
+    XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(methodResponseEltP),
+                               "methodResponse"));
+
+    if (xml_element_children_size(methodResponseEltP) == 1) {
+        xml_element * const child =
+            xml_element_children(methodResponseEltP)[0];
+        
+        if (xmlrpc_streq(xml_element_name(child), "params")) {
+            /* It's a successful response */
+            parseParamsElement(envP, child, resultPP);
+            *faultStringP = NULL;
+        } else if (xmlrpc_streq(xml_element_name(child), "fault")) {
+            /* It's a failure response */
+            parseFaultElement(envP, child, faultCodeP, faultStringP);
+        } else
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_PARSE_ERROR,
+                "<methodResponse> must contain <params> or <fault>, "
+                "but contains <%s>.", xml_element_name(child));
+    } else
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_PARSE_ERROR,
+            "<methodResponse> has %u children, should have 1.",
+            xml_element_children_size(methodResponseEltP));
+}
+
+
+
+void
+xmlrpc_parse_response2(xmlrpc_env *    const envP,
+                       const char *    const xmlData,
+                       size_t          const xmlDataLen,
+                       xmlrpc_value ** const resultPP,
+                       int *           const faultCodeP,
+                       const char **   const faultStringP) {
+/*----------------------------------------------------------------------------
+  Given some XML text, attempt to parse it as an XML-RPC response.
+
+  If the response is a regular, valid response, return a new reference
+  to the appropriate value as *resultP and return NULL as
+  *faultStringP and nothing as *faultCodeP.
+
+  If the response valid, but indicates a failure of the RPC, return the
+  fault string in newly malloc'ed space as *faultStringP and the fault
+  code as *faultCodeP and nothing as *resultP.
+
+  If the XML text is not a valid response or something prevents us from
+  parsing it, return a description of the error as *envP and nothing else.
+-----------------------------------------------------------------------------*/
+    xml_element * response;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(xmlData != NULL);
+
+    /* SECURITY: Last-ditch attempt to make sure our content length is legal.
+    ** XXX - This check occurs too late to prevent an attacker from creating
+    ** an enormous memory block, so you should try to enforce it
+    ** *before* reading any data off the network. */
+    if (xmlDataLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_LIMIT_EXCEEDED_ERROR,
+            "XML-RPC response too large.  Our limit is %u characters.  "
+            "We got %u characters",
+            xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID), xmlDataLen);
+    else {
+        xml_parse(envP, xmlData, xmlDataLen, &response);
+        if (!envP->fault_occurred) {
+            /* Pick apart and verify our structure. */
+            if (xmlrpc_streq(xml_element_name(response), "methodResponse")) {
+                parseMethodResponseElt(envP, response,
+                                       resultPP, faultCodeP, faultStringP);
+            } else
+                xmlrpc_env_set_fault_formatted(
+                    envP, XMLRPC_PARSE_ERROR,
+                    "XML-RPC response must consist of a "
+                    "<methodResponse> element.  This has a <%s> instead.",
+                    xml_element_name(response));
+            
+            xml_element_free(response);
+        }
+    }
+}
+
+
+
+xmlrpc_value *
+xmlrpc_parse_response(xmlrpc_env * const envP,
+                      const char * const xmlData,
+                      size_t       const xmlDataLen) {
+/*----------------------------------------------------------------------------
+   This exists for backward compatibility.  It is like
+   xmlrpc_parse_response2(), except that it merges the concepts of a
+   failed RPC and an error in executing the RPC.
+-----------------------------------------------------------------------------*/
+    xmlrpc_value * retval;
+    xmlrpc_value * result;
+    const char * faultString;
+    int faultCode;
+
+    xmlrpc_parse_response2(envP, xmlData, xmlDataLen,
+                           &result, &faultCode, &faultString);
+    
+    if (envP->fault_occurred)
+        retval = NULL;
+    else {
+        if (faultString) {
+            xmlrpc_env_set_fault(envP, faultCode, faultString);
+            xmlrpc_strfree(faultString);
+            retval = NULL;
+        } else
+            retval = result;  /* transfer reference */
+    }
+    return retval;
+}
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/src/xmlrpc_serialize.c b/src/xmlrpc_serialize.c
new file mode 100644 (file)
index 0000000..53223ca
--- /dev/null
@@ -0,0 +1,611 @@
+/* Copyright information is at end of file */
+
+#include "xmlrpc_config.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+
+#define CRLF "\015\012"
+#define SMALL_BUFFER_SZ (128)
+#define XML_PROLOGUE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"CRLF
+
+
+/*=========================================================================
+**  format_out
+**=========================================================================
+**  A lightweight print routine for use with various serialization
+**  functions. Only use this routine for printing small objects--it uses
+**  a fixed-size internal buffer and returns an error on overflow.
+**  In particular, do NOT use this routine to print XML-RPC string values!
+*/
+
+static void 
+format_out(xmlrpc_env *env,
+           xmlrpc_mem_block *output,
+           char *format_string,
+           ...) {
+
+    va_list args;
+    char buffer[SMALL_BUFFER_SZ];
+    int count;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+
+    va_start(args, format_string);
+
+    /* We assume that this function is present and works correctly. Right. */
+    count = vsnprintf(buffer, SMALL_BUFFER_SZ, format_string, args);
+
+    /* Old C libraries return -1 if vsnprintf overflows its buffer.
+    ** New C libraries return the number of characters which *would* have
+    ** been printed if the error did not occur. This is impressively vile.
+    ** Thank the C99 committee for this bright idea. But wait! We also
+    ** need to keep track of the trailing NULL. */
+    if (count < 0 || count >= (SMALL_BUFFER_SZ - 1))
+    XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR,
+                "format_out overflowed internal buffer");
+
+    /* Append our new data to our output. */
+    XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, buffer, count);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+cleanup:
+    va_end(args);
+}
+
+
+
+static void 
+assertValidUtf8(const char * const str ATTR_UNUSED,
+                size_t       const len ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+   Assert that the string 'str' of length 'len' is valid UTF-8.
+-----------------------------------------------------------------------------*/
+#if !defined NDEBUG
+    /* Check the assertion; if it's false, issue a message to
+       Standard Error, but otherwise ignore it.
+    */
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+    xmlrpc_validate_utf8(&env, str, len);
+    if (env.fault_occurred)
+        fprintf(stderr, "*** xmlrpc-c WARNING ***: %s (%s)\n",
+                "Xmlrpc-c sending corrupted UTF-8 data to network",
+                env.fault_string);
+    xmlrpc_env_clean(&env);
+#endif
+}
+
+
+
+static size_t
+escapedSize(const char * const chars,
+            size_t       const len) {
+    
+    size_t size;
+    size_t i;
+
+    size = 0;
+    for (i = 0; i < len; ++i) {
+        if (chars[i] == '<')
+            size += 4; /* &lt; */
+        else if (chars[i] == '>')
+            size += 4; /* &gt; */
+        else if (chars[i] == '&')
+            size += 5; /* &amp; */
+        else
+            size += 1;
+    }
+    return size;
+}
+
+
+
+static void
+escapeForXml(xmlrpc_env *        const envP, 
+             const char *        const chars,
+             size_t              const len,
+             xmlrpc_mem_block ** const outputPP) {
+/*----------------------------------------------------------------------------
+   Escape & and < in a UTF-8 string so as to make it suitable for the
+   content of an XML element.  I.e. turn them into entity references
+   &amp; and &lt;.  Also change > to &gt;, even though not required
+   for XML, for symmetry.
+-----------------------------------------------------------------------------*/
+    xmlrpc_mem_block * outputP;
+    size_t outputSize;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(chars != NULL);
+
+    assertValidUtf8(chars, len);
+
+    /* Note that in UTF-8, any byte that has high bit of zero is a
+       character all by itself (every byte of a multi-byte UTF-8 character
+       has the high bit set).  Also, the Unicode code points < 128 are
+       identical to the ASCII ones.
+    */
+
+    outputSize = escapedSize(chars, len);
+
+    outputP = XMLRPC_MEMBLOCK_NEW(char, envP, outputSize);
+    if (!envP->fault_occurred) {
+        char * p;
+        size_t i;
+        p = XMLRPC_MEMBLOCK_CONTENTS(char, outputP); /* Start at beginning */
+
+        for (i = 0; i < len; i++) {
+            if (chars[i] == '<') {
+                memcpy(p, "&lt;", 4);
+                p += 4;
+            } else if (chars[i] == '>') {
+                memcpy(p, "&gt;", 4);
+                p += 4;
+            } else if (chars[i] == '&') {
+                memcpy(p, "&amp;", 5);
+                p += 5;
+            } else {
+                *p = chars[i];
+                p += 1;
+            }
+        }
+        *outputPP = outputP;
+        assert(p == XMLRPC_MEMBLOCK_CONTENTS(char, outputP) + outputSize);
+
+        if (envP->fault_occurred)
+            XMLRPC_MEMBLOCK_FREE(char, outputP);
+    }
+}
+
+
+
+static void 
+serializeUtf8MemBlock(xmlrpc_env *       const envP,
+                      xmlrpc_mem_block * const outputP,
+                      xmlrpc_mem_block * const inputP) {
+/*----------------------------------------------------------------------------
+   Append the characters in *inputP to the XML stream in *outputP.
+
+   *inputP contains Unicode characters in UTF-8.
+
+   We assume *inputP ends with a NUL character that marks end of
+   string, and we ignore that.  (There might also be NUL characters
+   inside the string, though).
+-----------------------------------------------------------------------------*/
+    xmlrpc_mem_block * escapedP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(outputP != NULL);
+    XMLRPC_ASSERT(inputP != NULL);
+
+    escapeForXml(envP,
+                 XMLRPC_MEMBLOCK_CONTENTS(const char, inputP),
+                 XMLRPC_MEMBLOCK_SIZE(const char, inputP) - 1,
+                    /* -1 is for the terminating NUL */
+                 &escapedP);
+    if (!envP->fault_occurred) {
+        const char * const contents =
+            XMLRPC_MEMBLOCK_CONTENTS(const char, escapedP);
+        size_t const size = XMLRPC_MEMBLOCK_SIZE(char, escapedP);
+    
+        XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, contents, size);
+
+        XMLRPC_MEMBLOCK_FREE(const char, escapedP);
+    }
+}
+
+
+
+static void 
+xmlrpc_serialize_base64_data(xmlrpc_env *       const envP,
+                             xmlrpc_mem_block * const output,
+                             unsigned char *    const data, 
+                             size_t             const len) {
+/*----------------------------------------------------------------------------
+   Encode the 'len' bytes at 'data' in base64 ASCII and append the result to
+   'output'.
+-----------------------------------------------------------------------------*/
+    xmlrpc_mem_block * encoded;
+
+    encoded = xmlrpc_base64_encode(envP, data, len);
+    if (!envP->fault_occurred) {
+        unsigned char * const contents =
+            XMLRPC_MEMBLOCK_CONTENTS(unsigned char, encoded);
+        size_t const size = 
+            XMLRPC_MEMBLOCK_SIZE(unsigned char, encoded);
+        
+        XMLRPC_MEMBLOCK_APPEND(char, envP, output, contents, size);
+        
+        XMLRPC_MEMBLOCK_FREE(char, encoded);
+    }
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_serialize_struct
+**=========================================================================
+**  Dump the contents of a struct.
+*/                
+
+static void 
+xmlrpc_serialize_struct(xmlrpc_env *env,
+                        xmlrpc_mem_block *output,
+                        xmlrpc_value *strct) {
+
+    size_t size;
+    size_t i;
+    xmlrpc_value *key, *value;
+
+    format_out(env, output, "<struct>"CRLF);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    size = xmlrpc_struct_size(env, strct);
+    XMLRPC_FAIL_IF_FAULT(env);
+    for (i = 0; i < size; i++) {
+        xmlrpc_struct_get_key_and_value(env, strct, i, &key, &value);
+        XMLRPC_FAIL_IF_FAULT(env);
+        format_out(env, output, "<member><name>");
+        XMLRPC_FAIL_IF_FAULT(env);
+        serializeUtf8MemBlock(env, output, &key->_block);
+        XMLRPC_FAIL_IF_FAULT(env);
+        format_out(env, output, "</name>"CRLF);
+        XMLRPC_FAIL_IF_FAULT(env);
+        xmlrpc_serialize_value(env, output, value);
+        XMLRPC_FAIL_IF_FAULT(env);
+        format_out(env, output, "</member>"CRLF);
+        XMLRPC_FAIL_IF_FAULT(env);
+    }
+
+    format_out(env, output, "</struct>");
+    XMLRPC_FAIL_IF_FAULT(env);
+
+cleanup:
+    return;
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_serialize_value
+**=========================================================================
+**  Dump a value in the appropriate fashion.
+*/                
+
+void 
+xmlrpc_serialize_value(xmlrpc_env *env,
+                       xmlrpc_mem_block *output,
+                       xmlrpc_value *value) {
+
+    xmlrpc_value *item;
+    size_t size;
+    unsigned char* contents;
+    size_t i;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT(output != NULL);
+    XMLRPC_ASSERT_VALUE_OK(value);
+
+    /* Print our ubiquitous header. */
+    format_out(env, output, "<value>");
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    switch (value->_type) {
+
+    case XMLRPC_TYPE_INT:
+        /* XXX - We assume that '%i' is the appropriate format specifier
+        ** for an xmlrpc_int32 value. We should add some test cases to
+        ** make sure this works. */
+        format_out(env, output, "<i4>%i</i4>", value->_value.i);
+        break;
+
+    case XMLRPC_TYPE_BOOL:
+        /* XXX - We assume that '%i' is the appropriate format specifier
+        ** for an xmlrpc_bool value. */
+        format_out(env, output, "<boolean>%i</boolean>",
+                   (value->_value.b) ? 1 : 0);
+        break;
+
+    case XMLRPC_TYPE_DOUBLE:
+        /* We must output a number of the form [+-]?\d*.\d*. */
+        format_out(env, output, "<double>%f</double>", value->_value.d);
+        break;
+
+    case XMLRPC_TYPE_STRING:
+        format_out(env, output, "<string>");
+        XMLRPC_FAIL_IF_FAULT(env);
+        serializeUtf8MemBlock(env, output, &value->_block);
+        XMLRPC_FAIL_IF_FAULT(env);
+        format_out(env, output, "</string>");
+        break;
+
+    case XMLRPC_TYPE_ARRAY:
+        format_out(env, output, "<array><data>"CRLF);
+        XMLRPC_FAIL_IF_FAULT(env);
+
+        /* Serialize each item. */
+        size = xmlrpc_array_size(env, value);
+        XMLRPC_FAIL_IF_FAULT(env);
+        for (i = 0; i < size; i++) {
+            item = xmlrpc_array_get_item(env, value, i);
+            XMLRPC_FAIL_IF_FAULT(env);
+            xmlrpc_serialize_value(env, output, item);
+            XMLRPC_FAIL_IF_FAULT(env);
+            format_out(env, output, CRLF);
+            XMLRPC_FAIL_IF_FAULT(env);
+        }
+
+        format_out(env, output, "</data></array>");
+        break;
+
+    case XMLRPC_TYPE_STRUCT:
+        xmlrpc_serialize_struct(env, output, value);
+        break;
+
+    case XMLRPC_TYPE_BASE64:
+        format_out(env, output, "<base64>"CRLF);
+        XMLRPC_FAIL_IF_FAULT(env);
+        contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(unsigned char,
+                                                   &value->_block);
+        size = XMLRPC_TYPED_MEM_BLOCK_SIZE(unsigned char, &value->_block);
+        xmlrpc_serialize_base64_data(env, output, contents, size);
+        XMLRPC_FAIL_IF_FAULT(env);
+        format_out(env, output, "</base64>");
+        break;      
+
+    case XMLRPC_TYPE_DATETIME:
+        format_out(env, output, "<dateTime.iso8601>");
+        XMLRPC_FAIL_IF_FAULT(env);
+        serializeUtf8MemBlock(env, output, &value->_block);
+        XMLRPC_FAIL_IF_FAULT(env);
+        format_out(env, output, "</dateTime.iso8601>");
+        break;
+
+    case XMLRPC_TYPE_C_PTR:
+        xmlrpc_env_set_fault_formatted(
+            env, XMLRPC_INTERNAL_ERROR,
+            "Tried to serialize a C pointer value.");
+        break;
+
+    case XMLRPC_TYPE_NIL:
+        format_out(env, output, "<nil/>");
+        XMLRPC_FAIL_IF_FAULT(env);
+        break;
+
+    case XMLRPC_TYPE_DEAD:
+        xmlrpc_env_set_fault_formatted(
+            env, XMLRPC_INTERNAL_ERROR,
+            "Tried to serialize a deaad value.");
+        break;
+
+    default:
+        xmlrpc_env_set_fault_formatted(
+            env, XMLRPC_INTERNAL_ERROR,
+            "Invalid xmlrpc_value type: %d", value->_type);
+    }
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Print our ubiquitous footer. */
+    format_out(env, output, "</value>");
+    XMLRPC_FAIL_IF_FAULT(env);
+
+ cleanup:
+    return;
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_serialize_params
+**=========================================================================
+**  Serialize a list as a set of parameters.
+*/                
+
+void 
+xmlrpc_serialize_params(xmlrpc_env *env,
+                        xmlrpc_mem_block *output,
+                        xmlrpc_value *param_array) {
+
+    size_t size, i;
+    xmlrpc_value *item;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT(output != NULL);
+    XMLRPC_ASSERT_VALUE_OK(param_array);
+
+    format_out(env, output, "<params>"CRLF);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Dump each parameter. */
+    size = xmlrpc_array_size(env, param_array);
+    XMLRPC_FAIL_IF_FAULT(env);
+    for (i = 0; i < size; i++) {
+        format_out(env, output, "<param>");
+        XMLRPC_FAIL_IF_FAULT(env);
+        item = xmlrpc_array_get_item(env, param_array, i);
+        XMLRPC_FAIL_IF_FAULT(env);
+        xmlrpc_serialize_value(env, output, item);
+        XMLRPC_FAIL_IF_FAULT(env);
+        format_out(env, output, "</param>"CRLF);
+        XMLRPC_FAIL_IF_FAULT(env);
+    }
+
+    format_out(env, output, "</params>"CRLF);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+ cleanup:    
+    return;
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_serialize_call
+**=========================================================================
+**  Serialize an XML-RPC call.
+*/                
+
+void 
+xmlrpc_serialize_call(xmlrpc_env *       const env,
+                      xmlrpc_mem_block * const output,
+                      const char *       const method_name,
+                      xmlrpc_value *     const param_array) {
+
+    xmlrpc_mem_block * encodedP;
+    char *contents;
+    size_t size;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT(output != NULL);
+    XMLRPC_ASSERT(method_name != NULL);
+    XMLRPC_ASSERT_VALUE_OK(param_array);
+    
+    /* Set up our error-handling preconditions. */
+    encodedP = NULL;
+
+    /* Dump our header. */
+    format_out(env, output, XML_PROLOGUE);
+    XMLRPC_FAIL_IF_FAULT(env);
+    format_out(env, output, "<methodCall>"CRLF"<methodName>");
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Dump the method name. */
+    escapeForXml(env, method_name, strlen(method_name), &encodedP);
+    XMLRPC_FAIL_IF_FAULT(env);
+    contents = XMLRPC_MEMBLOCK_CONTENTS(char, encodedP);
+    size = XMLRPC_MEMBLOCK_SIZE(char, encodedP);
+    XMLRPC_MEMBLOCK_APPEND(char, env, output, contents, size);
+    XMLRPC_FAIL_IF_FAULT(env);    
+
+    /* Dump our parameters and footer. */
+    format_out(env, output, "</methodName>"CRLF);
+    XMLRPC_FAIL_IF_FAULT(env);
+    xmlrpc_serialize_params(env, output, param_array);
+    XMLRPC_FAIL_IF_FAULT(env);
+    format_out(env, output, "</methodCall>"CRLF);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+ cleanup:
+    if (encodedP)
+        XMLRPC_MEMBLOCK_FREE(char, encodedP);
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_serialize_response
+**=========================================================================
+**  Serialize the (non-fault) response to an XML-RPC call.
+*/                
+
+void 
+xmlrpc_serialize_response (xmlrpc_env *env,
+                           xmlrpc_mem_block *output,
+                           xmlrpc_value *value) {
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT(output != NULL);
+    XMLRPC_ASSERT_VALUE_OK(value);
+
+    format_out(env, output, XML_PROLOGUE);
+    XMLRPC_FAIL_IF_FAULT(env);
+    format_out(env, output, "<methodResponse>"CRLF"<params>"CRLF"<param>");
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    xmlrpc_serialize_value(env, output, value);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    format_out(env, output,
+               "</param>"CRLF"</params>"CRLF"</methodResponse>"CRLF);
+    XMLRPC_FAIL_IF_FAULT(env);
+    
+ cleanup:
+    return;
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_serialize_fault
+**=========================================================================
+**  Serialize an XML-RPC fault.
+**
+**  If this function fails, it will set up the first env argument. You'll
+**  need to take some other drastic action to produce a serialized fault
+**  of your own. (This function should only fail in an out-of-memory
+**  situation, AFAIK.)
+*/                
+
+void 
+xmlrpc_serialize_fault(xmlrpc_env *env,
+                       xmlrpc_mem_block *output,
+                       xmlrpc_env *fault) {
+
+    xmlrpc_value *strct;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT(output != NULL);
+    XMLRPC_ASSERT(fault != NULL && fault->fault_occurred);
+
+    /* Set up our error-handling preconditions. */
+    strct = NULL;
+
+    /* Build a fault structure. */
+    strct = xmlrpc_build_value(env, "{s:i,s:s}",
+                   "faultCode", (xmlrpc_int32) fault->fault_code,
+                   "faultString", fault->fault_string);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Output our header. */
+    format_out(env, output, XML_PROLOGUE);
+    XMLRPC_FAIL_IF_FAULT(env);
+    format_out(env, output, "<methodResponse>"CRLF"<fault>"CRLF);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Serialize our fault structure. */
+    xmlrpc_serialize_value(env, output, strct);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Output our footer. */
+    format_out(env, output, CRLF"</fault>"CRLF"</methodResponse>"CRLF);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+ cleanup:
+    if (strct)
+        xmlrpc_DECREF(strct);
+}
+
+
+
+
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
diff --git a/src/xmlrpc_server_abyss.c b/src/xmlrpc_server_abyss.c
new file mode 100644 (file)
index 0000000..310a8c1
--- /dev/null
@@ -0,0 +1,1201 @@
+/* Copyright information is at the end of the file */
+
+#include "xmlrpc_config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <fcntl.h>
+#ifdef _WIN32
+#  include <io.h>
+#else
+#  include <signal.h>
+#  include <sys/wait.h>
+#  include <grp.h>
+#endif
+
+#include "mallocvar.h"
+#include "xmlrpc-c/abyss.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "xmlrpc-c/base_int.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/server_abyss.h"
+
+
+/*=========================================================================
+**  die_if_fault_occurred
+**=========================================================================
+**  If certain kinds of out-of-memory errors occur during server setup,
+**  we want to quit and print an error.
+*/
+
+static void die_if_fault_occurred(xmlrpc_env *env) {
+    if (env->fault_occurred) {
+        fprintf(stderr, "Unexpected XML-RPC fault: %s (%d)\n",
+                env->fault_string, env->fault_code);
+        exit(1);
+    }
+}
+
+
+
+static void
+addAuthCookie(xmlrpc_env * const envP,
+              TSession *   const abyssSessionP,
+              const char * const authCookie) {
+
+    const char * cookieResponse;
+    
+    xmlrpc_asprintf(&cookieResponse, "auth=%s", authCookie);
+    
+    if (cookieResponse == xmlrpc_strsol)
+        xmlrpc_faultf(envP, "Insufficient memory to generate cookie "
+                      "response header.");
+    else {
+        ResponseAddField(abyssSessionP, "Set-Cookie", cookieResponse);
+    
+        xmlrpc_strfree(cookieResponse);
+    }
+}   
+    
+
+
+static void 
+sendXmlData(xmlrpc_env * const envP,
+            TSession *   const abyssSessionP, 
+            const char * const body, 
+            size_t       const len,
+            bool         const chunked) {
+/*----------------------------------------------------------------------------
+   Generate an HTTP response containing body 'body' of length 'len'
+   characters.
+
+   This is meant to run in the context of an Abyss URI handler for
+   Abyss session 'abyssSessionP'.
+-----------------------------------------------------------------------------*/
+    const char * http_cookie = NULL;
+        /* This used to set http_cookie to getenv("HTTP_COOKIE"), but
+           that doesn't make any sense -- environment variables are not
+           appropriate for this.  So for now, cookie code is disabled.
+           - Bryan 2004.10.03.
+        */
+
+    /* Various bugs before Xmlrpc-c 1.05 caused the response to be not
+       chunked in the most basic case, but chunked if the client explicitly
+       requested keepalive.  I think it's better not to chunk, because
+       it's simpler, so I removed this in 1.05.  I don't know what the
+       purpose of chunking would be, and an original comment suggests
+       the author wasn't sure chunking was a good idea.
+
+       In 1.06 we added the user option to chunk.
+    */
+    if (chunked)
+        ResponseChunked(abyssSessionP);
+
+    ResponseStatus(abyssSessionP, 200);
+
+    if (http_cookie)
+        /* There's an auth cookie, so pass it back in the response. */
+        addAuthCookie(envP, abyssSessionP, http_cookie);
+
+    if ((size_t)(uint32_t)len != len)
+        xmlrpc_faultf(envP, "XML-RPC method generated a response too "
+                      "large for Abyss to send");
+    else {
+        uint32_t const abyssLen = (uint32_t)len;
+
+        ResponseContentType(abyssSessionP, "text/xml; charset=\"utf-8\"");
+        ResponseContentLength(abyssSessionP, abyssLen);
+        
+        ResponseWriteStart(abyssSessionP);
+        ResponseWriteBody(abyssSessionP, body, abyssLen);
+        ResponseWriteEnd(abyssSessionP);
+    }
+}
+
+
+
+static void
+sendError(TSession *   const abyssSessionP, 
+          unsigned int const status) {
+/*----------------------------------------------------------------------------
+  Send an error response back to the client.
+   
+-----------------------------------------------------------------------------*/
+    ResponseStatus(abyssSessionP, (uint16_t) status);
+    ResponseError(abyssSessionP);
+}
+
+
+
+static void
+traceChunkRead(TSession * const abyssSessionP) {
+
+    fprintf(stderr, "XML-RPC handler got a chunk of %u bytes\n",
+            (unsigned int)SessionReadDataAvail(abyssSessionP));
+}
+
+
+
+static void
+refillBufferFromConnection(xmlrpc_env * const envP,
+                           TSession *   const abyssSessionP,
+                           const char * const trace) {
+/*----------------------------------------------------------------------------
+   Get the next chunk of data from the connection into the buffer.
+-----------------------------------------------------------------------------*/
+    abyss_bool succeeded;
+
+    succeeded = SessionRefillBuffer(abyssSessionP);
+
+    if (!succeeded)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TIMEOUT_ERROR, "Timed out waiting for "
+            "client to send its POST data");
+    else {
+        if (trace)
+            traceChunkRead(abyssSessionP);
+    }
+}
+
+
+
+static void
+getBody(xmlrpc_env *        const envP,
+        TSession *          const abyssSessionP,
+        size_t              const contentSize,
+        const char *        const trace,
+        xmlrpc_mem_block ** const bodyP) {
+/*----------------------------------------------------------------------------
+   Get the entire body, which is of size 'contentSize' bytes, from the
+   Abyss session and return it as the new memblock *bodyP.
+
+   The first chunk of the body may already be in Abyss's buffer.  We
+   retrieve that before reading more.
+-----------------------------------------------------------------------------*/
+    xmlrpc_mem_block * body;
+
+    if (trace)
+        fprintf(stderr, "XML-RPC handler processing body.  "
+                "Content Size = %u bytes\n", (unsigned)contentSize);
+
+    body = xmlrpc_mem_block_new(envP, 0);
+    if (!envP->fault_occurred) {
+        size_t bytesRead;
+        const char * chunkPtr;
+        size_t chunkLen;
+
+        bytesRead = 0;
+
+        while (!envP->fault_occurred && bytesRead < contentSize) {
+            SessionGetReadData(abyssSessionP, contentSize - bytesRead, 
+                               &chunkPtr, &chunkLen);
+            bytesRead += chunkLen;
+
+            assert(bytesRead <= contentSize);
+
+            XMLRPC_MEMBLOCK_APPEND(char, envP, body, chunkPtr, chunkLen);
+            if (bytesRead < contentSize)
+                refillBufferFromConnection(envP, abyssSessionP, trace);
+        }
+        if (envP->fault_occurred)
+            xmlrpc_mem_block_free(body);
+        else
+            *bodyP = body;
+    }
+}
+
+
+
+static void
+storeCookies(TSession *     const httpRequestP,
+             unsigned int * const httpErrorP) {
+/*----------------------------------------------------------------------------
+   Get the cookie settings from the HTTP headers and remember them for
+   use in responses.
+-----------------------------------------------------------------------------*/
+    const char * const cookie = RequestHeaderValue(httpRequestP, "cookie");
+    if (cookie) {
+        /* 
+           Setting the value in an environment variable doesn't make
+           any sense.  So for now, cookie code is disabled.
+           -Bryan 04.10.03.
+
+        setenv("HTTP_COOKIE", cookie, 1);
+        */
+    }
+    /* TODO: parse HTTP_COOKIE to find auth pair, if there is one */
+
+    *httpErrorP = 0;
+}
+
+
+
+
+static void
+validateContentType(TSession *     const httpRequestP,
+                    unsigned int * const httpErrorP) {
+/*----------------------------------------------------------------------------
+   If the client didn't specify a content-type of "text/xml", return      
+   "400 Bad Request".  We can't allow the client to default this header,
+   because some firewall software may rely on all XML-RPC requests
+   using the POST method and a content-type of "text/xml". 
+-----------------------------------------------------------------------------*/
+    const char * const content_type =
+        RequestHeaderValue(httpRequestP, "content-type");
+
+    if (content_type == NULL)
+        *httpErrorP = 400;
+    else {
+        const char * const sempos = strchr(content_type, ';');
+        unsigned int baselen;
+            /* Length of the base portion of the content type, e.g.
+               "text/xml" int "text/xml;charset=utf-8"
+            */
+
+        if (sempos)
+            baselen = sempos - content_type;
+        else
+            baselen = strlen(content_type);
+
+        if (!xmlrpc_strneq(content_type, "text/xml", baselen))
+            *httpErrorP = 400;
+        else
+            *httpErrorP = 0;
+    }
+}
+
+
+
+static void
+processContentLength(TSession *     const httpRequestP,
+                     size_t *       const inputLenP,
+                     unsigned int * const httpErrorP) {
+/*----------------------------------------------------------------------------
+  Make sure the content length is present and non-zero.  This is
+  technically required by XML-RPC, but we only enforce it because we
+  don't want to figure out how to safely handle HTTP < 1.1 requests
+  without it.  If the length is missing, return "411 Length Required". 
+-----------------------------------------------------------------------------*/
+    const char * const content_length = 
+        RequestHeaderValue(httpRequestP, "content-length");
+
+    if (content_length == NULL)
+        *httpErrorP = 411;
+    else {
+        if (content_length[0] == '\0')
+            *httpErrorP = 400;
+        else {
+            unsigned long contentLengthValue;
+            char * tail;
+        
+            contentLengthValue = strtoul(content_length, &tail, 10);
+        
+            if (*tail != '\0')
+                /* There's non-numeric crap in the length */
+                *httpErrorP = 400;
+            else if (contentLengthValue < 1)
+                *httpErrorP = 400;
+            else if ((unsigned long)(size_t)contentLengthValue 
+                     != contentLengthValue)
+                *httpErrorP = 400;
+            else {
+                *httpErrorP = 0;
+                *inputLenP = (size_t)contentLengthValue;
+            }
+        }
+    }
+}
+
+
+
+static void
+traceHandlerCalled(TSession * const abyssSessionP) {
+    
+    const char * methodDesc;
+    const TRequestInfo * requestInfoP;
+
+    fprintf(stderr, "xmlrpc_server_abyss URI path handler called.\n");
+
+    SessionGetRequestInfo(abyssSessionP, &requestInfoP);
+
+    fprintf(stderr, "URI = '%s'\n", requestInfoP->uri);
+
+    switch (requestInfoP->method) {
+    case m_unknown: methodDesc = "unknown";   break;
+    case m_get:     methodDesc = "get";       break;
+    case m_put:     methodDesc = "put";       break;
+    case m_head:    methodDesc = "head";      break;
+    case m_post:    methodDesc = "post";      break;
+    case m_delete:  methodDesc = "delete";    break;
+    case m_trace:   methodDesc = "trace";     break;
+    case m_options: methodDesc = "m_options"; break;
+    default:        methodDesc = "?";
+    }
+    fprintf(stderr, "HTTP method = '%s'\n", methodDesc);
+
+    if (requestInfoP->query)
+        fprintf(stderr, "query (component of URL)='%s'\n",
+                requestInfoP->query);
+    else
+        fprintf(stderr, "URL has no query component\n");
+}
+
+
+
+static void
+processCall(TSession *        const abyssSessionP,
+            size_t            const contentSize,
+            xmlrpc_registry * const registryP,
+            bool              const wantChunk,
+            const char *      const trace) {
+/*----------------------------------------------------------------------------
+   Handle an RPC request.  This is an HTTP request that has the proper form
+   to be one of our RPCs.
+
+   Its content length is 'contentSize' bytes.
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+
+    if (trace)
+        fprintf(stderr,
+                "xmlrpc_server_abyss URI path handler processing RPC.\n");
+
+    xmlrpc_env_init(&env);
+
+    if (contentSize > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
+        xmlrpc_env_set_fault_formatted(
+            &env, XMLRPC_LIMIT_EXCEEDED_ERROR,
+            "XML-RPC request too large (%d bytes)", contentSize);
+    else {
+        xmlrpc_mem_block *body;
+        /* Read XML data off the wire. */
+        getBody(&env, abyssSessionP, contentSize, trace, &body);
+        if (!env.fault_occurred) {
+            xmlrpc_mem_block * output;
+            /* Process the RPC. */
+            output = xmlrpc_registry_process_call(
+                &env, registryP, NULL, 
+                XMLRPC_MEMBLOCK_CONTENTS(char, body),
+                XMLRPC_MEMBLOCK_SIZE(char, body));
+            if (!env.fault_occurred) {
+                /* Send out the result. */
+                sendXmlData(&env, abyssSessionP, 
+                            XMLRPC_MEMBLOCK_CONTENTS(char, output),
+                            XMLRPC_MEMBLOCK_SIZE(char, output),
+                            wantChunk);
+                
+                XMLRPC_MEMBLOCK_FREE(char, output);
+            }
+            XMLRPC_MEMBLOCK_FREE(char, body);
+        }
+    }
+    if (env.fault_occurred) {
+        if (env.fault_code == XMLRPC_TIMEOUT_ERROR)
+            sendError(abyssSessionP, 408); /* 408 Request Timeout */
+        else
+            sendError(abyssSessionP, 500); /* 500 Internal Server Error */
+    }
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+/****************************************************************************
+    Abyss handlers (to be registered with and called by Abyss)
+****************************************************************************/
+
+static const char * trace_abyss;
+
+
+
+struct uriHandlerXmlrpc {
+/*----------------------------------------------------------------------------
+   This is the part of an Abyss HTTP request handler (aka URI handler)
+   that is specific to the Xmlrpc-c handler.
+-----------------------------------------------------------------------------*/
+    xmlrpc_registry * registryP;
+    const char *      uriPath;  /* malloc'ed */
+    bool              chunkResponse;
+        /* The handler should chunk its response whenever possible */
+};
+
+
+
+static void
+termUriHandler(void * const arg) {
+
+    struct uriHandlerXmlrpc * const uriHandlerXmlrpcP = arg;
+
+    xmlrpc_strfree(uriHandlerXmlrpcP->uriPath);
+    free(uriHandlerXmlrpcP);
+}
+
+
+
+static void
+handleXmlrpcReq(URIHandler2 * const this,
+                TSession *    const abyssSessionP,
+                abyss_bool *  const handledP) {
+/*----------------------------------------------------------------------------
+   Our job is to look at this HTTP request that the Abyss server is
+   trying to process and see if we can handle it.  If it's an XML-RPC
+   call for this XML-RPC server, we handle it.  If it's not, we refuse
+   it and Abyss can try some other handler.
+
+   Our return code is TRUE to mean we handled it; FALSE to mean we didn't.
+
+   Note that failing the request counts as handling it, and not handling
+   it does not mean we failed it.
+
+   This is an Abyss HTTP Request handler -- type URIHandler2.
+-----------------------------------------------------------------------------*/
+    struct uriHandlerXmlrpc * const uriHandlerXmlrpcP = this->userdata;
+
+    const TRequestInfo * requestInfoP;
+
+    if (trace_abyss)
+        traceHandlerCalled(abyssSessionP);
+
+    SessionGetRequestInfo(abyssSessionP, &requestInfoP);
+
+    /* Note that requestInfoP->uri is not the whole URI.  It is just
+       the "file name" part of it.
+    */
+    if (strcmp(requestInfoP->uri, uriHandlerXmlrpcP->uriPath) != 0)
+        /* It's for the path (e.g. "/RPC2") that we're supposed to
+           handle.
+        */
+        *handledP = FALSE;
+    else {
+        *handledP = TRUE;
+
+        /* We understand only the POST HTTP method.  For anything else, return
+           "405 Method Not Allowed". 
+        */
+        if (requestInfoP->method != m_post)
+            sendError(abyssSessionP, 405);
+        else {
+            unsigned int httpError;
+            storeCookies(abyssSessionP, &httpError);
+            if (httpError)
+                sendError(abyssSessionP, httpError);
+            else {
+                unsigned int httpError;
+                validateContentType(abyssSessionP, &httpError);
+                if (httpError)
+                    sendError(abyssSessionP, httpError);
+                else {
+                    unsigned int httpError;
+                    size_t contentSize;
+
+                    processContentLength(abyssSessionP, 
+                                         &contentSize, &httpError);
+                    if (httpError)
+                        sendError(abyssSessionP, httpError);
+                    else 
+                        processCall(abyssSessionP, contentSize,
+                                    uriHandlerXmlrpcP->registryP,
+                                    uriHandlerXmlrpcP->chunkResponse,
+                                    trace_abyss);
+                }
+            }
+        }
+    }
+    if (trace_abyss)
+        fprintf(stderr, "xmlrpc_server_abyss URI path handler returning.\n");
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_server_abyss_default_handler
+**=========================================================================
+**  This handler returns a 404 Not Found for all requests. See the header
+**  for more documentation.
+*/
+
+static xmlrpc_bool 
+xmlrpc_server_abyss_default_handler(TSession * const sessionP) {
+
+    if (trace_abyss)
+        fprintf(stderr, "xmlrpc_server_abyss default handler called.\n");
+
+    sendError(sessionP, 404);
+
+    return TRUE;
+}
+
+
+
+static void 
+sigchld(int const signalClass ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+   This is a signal handler for a SIGCHLD signal (which informs us that
+   one of our child processes has terminated).
+
+   The only child processes we have are those that belong to the Abyss
+   server (and then only if the Abyss server was configured to use
+   forking as a threading mechanism), so we respond by passing the
+   signal on to the Abyss server.
+-----------------------------------------------------------------------------*/
+#ifndef WIN32
+    bool childrenLeft;
+    bool error;
+
+    assert(signalClass == SIGCHLD);
+
+    error = false;
+    childrenLeft = true;  /* initial assumption */
+    
+    /* Reap defunct children until there aren't any more. */
+    while (childrenLeft && !error) {
+        int status;
+        pid_t pid;
+
+        pid = waitpid((pid_t) -1, &status, WNOHANG);
+    
+        if (pid == 0)
+            childrenLeft = false;
+        else if (pid < 0) {
+            /* because of ptrace */
+            if (errno != EINTR)   
+                error = true;
+        } else
+            ServerHandleSigchld(pid);
+    }
+#endif /* WIN32 */
+}
+
+
+struct signalHandlers {
+    struct sigaction pipe;
+    struct sigaction chld;
+};
+
+
+
+static void
+setupSignalHandlers(struct signalHandlers * const oldHandlersP) {
+#ifndef WIN32
+    struct sigaction mysigaction;
+    
+    sigemptyset(&mysigaction.sa_mask);
+    mysigaction.sa_flags = 0;
+
+    /* This signal indicates connection closed in the middle */
+    mysigaction.sa_handler = SIG_IGN;
+    sigaction(SIGPIPE, &mysigaction, &oldHandlersP->pipe);
+    
+    /* This signal indicates a child process (request handler) has died */
+    mysigaction.sa_handler = sigchld;
+    sigaction(SIGCHLD, &mysigaction, &oldHandlersP->chld);
+#endif
+}    
+
+
+
+static void
+restoreSignalHandlers(struct signalHandlers const oldHandlers) {
+#ifndef WIN32
+
+    sigaction(SIGPIPE, &oldHandlers.pipe, NULL);
+    sigaction(SIGCHLD, &oldHandlers.chld, NULL);
+
+#endif
+}
+
+
+
+static void
+runServerDaemon(TServer *  const serverP,
+                runfirstFn const runfirst,
+                void *     const runfirstArg) {
+
+    struct signalHandlers oldHandlers;
+
+    setupSignalHandlers(&oldHandlers);
+
+    ServerUseSigchld(serverP);
+
+    ServerDaemonize(serverP);
+    
+    /* We run the user supplied runfirst after forking, but before accepting
+       connections (helpful when running with threads)
+    */
+    if (runfirst)
+        runfirst(runfirstArg);
+
+    ServerRun(serverP);
+
+    restoreSignalHandlers(oldHandlers);
+}
+
+
+
+static void
+setHandler(xmlrpc_env *      const envP,
+           TServer *         const srvP,
+           const char *      const uriPath,
+           xmlrpc_registry * const registryP,
+           bool              const chunkResponse) {
+    
+    struct uriHandlerXmlrpc * uriHandlerXmlrpcP;
+    URIHandler2 uriHandler;
+    abyss_bool success;
+
+    trace_abyss = getenv("XMLRPC_TRACE_ABYSS");
+                                 
+    MALLOCVAR_NOFAIL(uriHandlerXmlrpcP);
+
+    uriHandlerXmlrpcP->registryP     = registryP;
+    uriHandlerXmlrpcP->uriPath       = strdup(uriPath);
+    uriHandlerXmlrpcP->chunkResponse = chunkResponse;
+
+    uriHandler.handleReq2 = handleXmlrpcReq;
+    uriHandler.handleReq1 = NULL;
+    uriHandler.userdata   = uriHandlerXmlrpcP;
+    uriHandler.init       = NULL;
+    uriHandler.term       = &termUriHandler;
+
+    ServerAddHandler2(srvP, &uriHandler, &success);
+
+    if (!success)
+        xmlrpc_faultf(envP, "Abyss failed to register the Xmlrpc-c request "
+                      "handler.  ServerAddHandler2() failed.");
+
+    if (envP->fault_occurred)
+        free(uriHandlerXmlrpcP);
+}
+
+
+
+void
+xmlrpc_server_abyss_set_handler(xmlrpc_env *      const envP,
+                                TServer *         const srvP,
+                                const char *      const uriPath,
+                                xmlrpc_registry * const registryP) {
+
+    setHandler(envP, srvP, uriPath, registryP, false);
+}
+
+    
+
+static void
+setHandlers(TServer *         const srvP,
+            const char *      const uriPath,
+            xmlrpc_registry * const registryP,
+            bool              const chunkResponse) {
+
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    trace_abyss = getenv("XMLRPC_TRACE_ABYSS");
+                                 
+    setHandler(&env, srvP, uriPath, registryP, chunkResponse);
+    
+    if (env.fault_occurred)
+        abort();
+
+    ServerDefaultHandler(srvP, xmlrpc_server_abyss_default_handler);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_server_abyss_set_handlers2(TServer *         const srvP,
+                                  const char *      const uriPath,
+                                  xmlrpc_registry * const registryP) {
+
+    setHandlers(srvP, uriPath, registryP, false);
+}
+
+
+
+void
+xmlrpc_server_abyss_set_handlers(TServer *         const srvP,
+                                 xmlrpc_registry * const registryP) {
+
+    setHandlers(srvP, "/RPC2", registryP, false);
+}
+
+
+
+static void
+oldHighLevelAbyssRun(xmlrpc_env *                      const envP ATTR_UNUSED,
+                     const xmlrpc_server_abyss_parms * const parmsP,
+                     unsigned int                      const parmSize) {
+/*----------------------------------------------------------------------------
+   This is the old deprecated interface, where the caller of the 
+   xmlrpc_server_abyss API supplies an Abyss configuration file and
+   we use it to daemonize (fork into the background, chdir, set uid, etc.)
+   and run the Abyss server.
+
+   The new preferred interface, implemented by normalLevelAbyssRun(),
+   instead lets Caller set up the process environment himself and pass
+   Abyss parameters in memory.  That's a more conventional and
+   flexible API.
+-----------------------------------------------------------------------------*/
+    TServer server;
+    runfirstFn runfirst;
+    void * runfirstArg;
+    
+    DateInit();
+    
+    ServerCreate(&server, "XmlRpcServer", 8080, DEFAULT_DOCS, NULL);
+    
+    ConfReadServerFile(parmsP->config_file_name, &server);
+        
+    setHandlers(&server, "/RPC2", parmsP->registryP, false);
+        
+    ServerInit(&server);
+    
+    if (parmSize >= XMLRPC_APSIZE(runfirst_arg)) {
+        runfirst    = parmsP->runfirst;
+        runfirstArg = parmsP->runfirst_arg;
+    } else {
+        runfirst    = NULL;
+        runfirstArg = NULL;
+    }
+    runServerDaemon(&server, runfirst, runfirstArg);
+
+    ServerFree(&server);
+}
+
+
+
+static void
+setAdditionalServerParms(const xmlrpc_server_abyss_parms * const parmsP,
+                         unsigned int                      const parmSize,
+                         TServer *                         const serverP) {
+
+    /* The following ought to be parameters on ServerCreate(), but it
+       looks like plugging them straight into the TServer structure is
+       the only way to set them.  
+    */
+
+    if (parmSize >= XMLRPC_APSIZE(keepalive_timeout) &&
+        parmsP->keepalive_timeout > 0)
+        ServerSetKeepaliveTimeout(serverP, parmsP->keepalive_timeout);
+    if (parmSize >= XMLRPC_APSIZE(keepalive_max_conn) &&
+        parmsP->keepalive_max_conn > 0)
+        ServerSetKeepaliveMaxConn(serverP, parmsP->keepalive_max_conn);
+    if (parmSize >= XMLRPC_APSIZE(timeout) &&
+        parmsP->timeout > 0)
+        ServerSetTimeout(serverP, parmsP->timeout);
+    if (parmSize >= XMLRPC_APSIZE(dont_advertise))
+        ServerSetAdvertise(serverP, !parmsP->dont_advertise);
+}
+
+
+
+static void
+extractServerCreateParms(
+    xmlrpc_env *                      const envP,
+    const xmlrpc_server_abyss_parms * const parmsP,
+    unsigned int                      const parmSize,
+    abyss_bool *                      const socketBoundP,
+    unsigned int *                    const portNumberP,
+    TOsSocket *                       const socketFdP,
+    const char **                     const logFileNameP) {
+                   
+
+    if (parmSize >= XMLRPC_APSIZE(socket_bound))
+        *socketBoundP = parmsP->socket_bound;
+    else
+        *socketBoundP = FALSE;
+
+    if (*socketBoundP) {
+        if (parmSize < XMLRPC_APSIZE(socket_handle))
+            xmlrpc_faultf(envP, "socket_bound is true, but server parameter "
+                          "structure does not contain socket_handle (it's too "
+                          "short)");
+        else
+            *socketFdP = parmsP->socket_handle;
+    } else {
+        if (parmSize >= XMLRPC_APSIZE(port_number))
+            *portNumberP = parmsP->port_number;
+        else
+            *portNumberP = 8080;
+
+        if (*portNumberP > 0xffff)
+            xmlrpc_faultf(envP,
+                          "TCP port number %u exceeds the maximum possible "
+                          "TCP port number (65535)",
+                          *portNumberP);
+    }
+    if (!envP->fault_occurred) {
+        if (parmSize >= XMLRPC_APSIZE(log_file_name) &&
+            parmsP->log_file_name)
+            *logFileNameP = strdup(parmsP->log_file_name);
+        else
+            *logFileNameP = NULL;
+    }
+}
+
+
+
+static void
+createServerBoundSocket(xmlrpc_env * const envP,
+                        TOsSocket    const socketFd,
+                        const char * const logFileName,
+                        TServer *    const serverP,
+                        TSocket **   const socketPP) {
+
+    TSocket * socketP;
+    const char * error;
+    
+    SocketUnixCreateFd(socketFd, &socketP);
+    
+    if (!socketP)
+        xmlrpc_faultf(envP, "Unable to create Abyss socket out of "
+                      "file descriptor %d.", socketFd);
+    else {
+        ServerCreateSocket2(serverP, socketP, &error);
+        if (error) {
+            xmlrpc_faultf(envP, "Abyss failed to create server.  %s",
+                          error);
+            xmlrpc_strfree(error);
+        } else {
+            *socketPP = socketP;
+                    
+            ServerSetName(serverP, "XmlRpcServer");
+            
+            if (logFileName)
+                ServerSetLogFileName(serverP, logFileName);
+        }
+        if (envP->fault_occurred)
+                    SocketDestroy(socketP);
+    }
+}
+
+
+
+static void
+createServer(xmlrpc_env *                      const envP,
+             const xmlrpc_server_abyss_parms * const parmsP,
+             unsigned int                      const parmSize,
+             TServer *                         const serverP,
+             TSocket **                        const socketPP) {
+/*----------------------------------------------------------------------------
+   Create a bare server.  It will need further setup before it is ready
+   to use.
+-----------------------------------------------------------------------------*/
+    abyss_bool socketBound;
+    unsigned int portNumber;
+    TOsSocket socketFd;
+    const char * logFileName;
+
+    extractServerCreateParms(envP, parmsP, parmSize,
+                             &socketBound, &portNumber, &socketFd,
+                             &logFileName);
+
+    if (!envP->fault_occurred) {
+        if (socketBound)
+            createServerBoundSocket(envP, socketFd, logFileName,
+                                    serverP, socketPP);
+        else {
+            ServerCreate(serverP, "XmlRpcServer", portNumber, DEFAULT_DOCS, 
+                         logFileName);
+            
+            *socketPP = NULL;
+        }
+        if (logFileName)
+            xmlrpc_strfree(logFileName);
+    }
+}
+
+
+
+static bool
+chunkResponseParm(const xmlrpc_server_abyss_parms * const parmsP,
+                  unsigned int                      const parmSize) {
+
+    return
+        parmSize >= XMLRPC_APSIZE(chunk_response) &&
+        parmsP->chunk_response;
+}    
+
+
+
+static const char *
+uriPathParm(const xmlrpc_server_abyss_parms * const parmsP,
+            unsigned int                      const parmSize) {
+    
+    const char * uriPath;
+
+    if (parmSize >= XMLRPC_APSIZE(uri_path) && parmsP->uri_path)
+        uriPath = parmsP->uri_path;
+    else
+        uriPath = "/RPC2";
+
+    return uriPath;
+}
+
+
+
+static xmlrpc_server_shutdown_fn shutdownAbyss;
+
+static void
+shutdownAbyss(xmlrpc_env * const envP,
+              void *       const context,
+              const char * const comment ATTR_UNUSED) {
+/*----------------------------------------------------------------------------
+   Tell Abyss to wrap up whatever it's doing and shut down.
+
+   This is a server shutdown function to be registered in the method
+   registry, for use by the 'system.shutdown' system method.
+
+   After we return, Abyss will finish up the system.shutdown and any
+   other connections that are in progress, then the call to
+   ServerRun() etc. will return.  But Abyss may be stuck waiting for
+   something, such as the next HTTP connection.  In that case, until it
+   gets what it's waiting for, it won't even know it's supposed t shut
+   down.  In particular, a caller of system.shutdown may have to execute
+   one more RPC in order for the shutdown to happen.
+-----------------------------------------------------------------------------*/
+    TServer * const serverP = context;
+
+    xmlrpc_env_init(envP);
+    
+    ServerTerminate(serverP);
+}
+
+
+
+static void
+normalLevelAbyssRun(xmlrpc_env *                      const envP,
+                    const xmlrpc_server_abyss_parms * const parmsP,
+                    unsigned int                      const parmSize) {
+    
+    TServer server;
+    TSocket * socketP;
+
+    DateInit();
+
+    createServer(envP, parmsP, parmSize, &server, &socketP);
+
+    if (!envP->fault_occurred) {
+        struct signalHandlers oldHandlers;
+
+        setAdditionalServerParms(parmsP, parmSize, &server);
+
+        setHandlers(&server, uriPathParm(parmsP, parmSize), parmsP->registryP,
+                    chunkResponseParm(parmsP, parmSize));
+
+        ServerInit(&server);
+        
+        setupSignalHandlers(&oldHandlers);
+
+        ServerUseSigchld(&server);
+        
+        if (0)
+            /* Too much of a security risk.  In 1.07, there is a server
+               parameter to enable this.
+            */
+            xmlrpc_registry_set_shutdown(parmsP->registryP,
+                                         &shutdownAbyss, &server);
+        
+        ServerRun(&server);
+
+        restoreSignalHandlers(oldHandlers);
+
+        ServerFree(&server);
+
+        if (socketP)
+            SocketDestroy(socketP);
+    }
+}
+
+
+
+void
+xmlrpc_server_abyss(xmlrpc_env *                      const envP,
+                    const xmlrpc_server_abyss_parms * const parmsP,
+                    unsigned int                      const parmSize) {
+    XMLRPC_ASSERT_ENV_OK(envP);
+
+    if (parmSize < XMLRPC_APSIZE(registryP))
+        xmlrpc_faultf(envP,
+                      "You must specify members at least up through "
+                      "'registryP' in the server parameters argument.  "
+                      "That would mean the parameter size would be >= %lu "
+                      "but you specified a size of %u",
+                      XMLRPC_APSIZE(registryP), parmSize);
+    else {
+        if (parmsP->config_file_name)
+            oldHighLevelAbyssRun(envP, parmsP, parmSize);
+        else
+            normalLevelAbyssRun(envP, parmsP, parmSize);
+    }
+}
+
+
+
+/*=========================================================================
+  XML-RPC Server Method Registry
+
+  This is an old deprecated form of the server facilities that uses
+  global variables.
+=========================================================================*/
+
+/* These global variables must be treated as read-only after the
+   server has started.
+*/
+
+static TServer globalSrv;
+    /* When you use the old interface (xmlrpc_server_abyss_init(), etc.),
+       this is the Abyss server to which they refer.  Obviously, there can be
+       only one Abyss server per program using this interface.
+    */
+
+static xmlrpc_registry * builtin_registryP;
+
+
+
+void 
+xmlrpc_server_abyss_init_registry(void) {
+
+    /* This used to just create the registry and Caller would be
+       responsible for adding the handlers that use it.
+
+       But that isn't very modular -- the handlers and registry go
+       together; there's no sense in using the built-in registry and
+       not the built-in handlers because if you're custom building
+       something, you can just make your own regular registry.  So now
+       we tie them together, and we don't export our handlers.  
+    */
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+    builtin_registryP = xmlrpc_registry_new(&env);
+    die_if_fault_occurred(&env);
+    xmlrpc_env_clean(&env);
+
+    setHandlers(&globalSrv, "/RPC2", builtin_registryP, false);
+}
+
+
+
+xmlrpc_registry *
+xmlrpc_server_abyss_registry(void) {
+
+    /* This is highly deprecated.  If you want to mess with a registry,
+       make your own with xmlrpc_registry_new() -- don't mess with the
+       internal one.
+    */
+    return builtin_registryP;
+}
+
+
+
+/* A quick & easy shorthand for adding a method. */
+void 
+xmlrpc_server_abyss_add_method(char *        const method_name,
+                               xmlrpc_method const method,
+                               void *        const user_data) {
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+    xmlrpc_registry_add_method(&env, builtin_registryP, NULL, method_name,
+                               method, user_data);
+    die_if_fault_occurred(&env);
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_server_abyss_add_method_w_doc(char *        const method_name,
+                                     xmlrpc_method const method,
+                                     void *        const user_data,
+                                     char *        const signature,
+                                     char *        const help) {
+
+    xmlrpc_env env;
+    xmlrpc_env_init(&env);
+    xmlrpc_registry_add_method_w_doc(
+        &env, builtin_registryP, NULL, method_name,
+        method, user_data, signature, help);
+    die_if_fault_occurred(&env);
+    xmlrpc_env_clean(&env);    
+}
+
+
+
+void 
+xmlrpc_server_abyss_init(int          const flags ATTR_UNUSED, 
+                         const char * const config_file) {
+
+    DateInit();
+    MIMETypeInit();
+
+    ServerCreate(&globalSrv, "XmlRpcServer", 8080, DEFAULT_DOCS, NULL);
+    
+    ConfReadServerFile(config_file, &globalSrv);
+
+    xmlrpc_server_abyss_init_registry();
+        /* Installs /RPC2 handler and default handler that use the
+           built-in registry.
+        */
+
+    ServerInit(&globalSrv);
+}
+
+
+
+void 
+xmlrpc_server_abyss_run_first(runfirstFn const runfirst,
+                              void *     const runfirstArg) {
+    
+    runServerDaemon(&globalSrv, runfirst, runfirstArg);
+}
+
+
+
+void 
+xmlrpc_server_abyss_run(void) {
+    runServerDaemon(&globalSrv, NULL, NULL);
+}
+
+
+
+/*
+** Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+** There is more copyright information in the bottom half of this file. 
+** Please see it for more details. 
+*/
diff --git a/src/xmlrpc_server_cgi.c b/src/xmlrpc_server_cgi.c
new file mode 100644 (file)
index 0000000..4079542
--- /dev/null
@@ -0,0 +1,323 @@
+/* Copyright (C) 2001 by Eric Kidd. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+
+#include "xmlrpc_config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Windows NT stdout binary mode fix. */
+#ifdef _WIN32 
+#include <io.h> 
+#include <fcntl.h> 
+#endif 
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "xmlrpc-c/server_cgi.h"
+
+
+/*=========================================================================
+**  Output Routines
+**=========================================================================
+**  These routines send various kinds of responses to the server.
+*/
+
+static void 
+send_xml(const char * const xml_data,
+         size_t       const xml_len) {
+#ifdef _WIN32 
+    _setmode(_fileno(stdout), _O_BINARY); 
+#endif 
+    /* Send our CGI headers back to the server.
+    ** XXX - Coercing 'size_t' to 'unsigned long' might be unsafe under
+    ** really weird circumstances. */
+    fprintf(stdout, "Status: 200 OK\n");
+    /* Handle authentication cookie being sent back. */
+    if (getenv("HTTP_COOKIE_AUTH") != NULL)
+        fprintf(stdout, "Set-Cookie: auth=%s\n", getenv("HTTP_COOKIE_AUTH"));
+    fprintf(stdout, "Content-type: text/xml; charset=\"utf-8\"\n");
+    fprintf(stdout, "Content-length: %ld\n\n", (unsigned long) xml_len);
+
+    /* Blast out our data. */
+    fwrite(xml_data, sizeof(char), xml_len, stdout);
+}
+
+
+
+static void
+send_error(int          const code,
+           const char * const message,
+           xmlrpc_env * const env) {
+
+#ifdef _WIN32 
+    _setmode(_fileno(stdout), _O_BINARY); 
+#endif 
+    /* Send an error header. */
+    fprintf(stdout, "Status: %d %s\n", code, message);
+    fprintf(stdout, "Content-type: text/html\n\n");
+    
+    /* Send an error message. */
+    fprintf(stdout, "<title>%d %s</title>\n", code, message);
+    fprintf(stdout, "<h1>%d %s</h1>\n", code, message);
+    fprintf(stdout, "<p>An error occurred processing your request.</p>\n");
+
+    /* Print out the XML-RPC fault, if present. */
+    if (env && env->fault_occurred)
+        fprintf(stdout, "<p>XML-RPC Fault #%d: %s</p>\n",
+                env->fault_code, env->fault_string);
+}
+
+
+/*=========================================================================
+**  die_if_fault_occurred
+**=========================================================================
+**  Certain kinds of errors aren't worth the trouble of generating
+**  an XML-RPC fault. For these, we just send status 500 to our web server
+**  and log the fault to our server log.
+*/
+
+static void
+die_if_fault_occurred(xmlrpc_env * const env) {
+    if (env->fault_occurred) {
+        fprintf(stderr, "Unexpected XML-RPC fault: %s (%d)\n",
+                env->fault_string, env->fault_code);
+        send_error(500, "Internal Server Error", env);
+        exit(1);
+    }
+}
+
+
+/*=========================================================================
+**  Initialization, Cleanup & Method Registry
+**=========================================================================
+**  These are all related, so we group them together.
+*/
+
+static xmlrpc_registry * globalRegistryP;
+
+/*=========================================================================
+**  get_body
+**=========================================================================
+**  Slurp the body of the request into an xmlrpc_mem_block.
+*/
+
+static xmlrpc_mem_block *
+get_body(xmlrpc_env * const env,
+         size_t       const length) {
+
+    xmlrpc_mem_block *result;
+    char *contents;
+    size_t count;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+
+    /* Error-handling preconditions. */
+    result = NULL;
+
+#ifdef _WIN32 
+    /* Fix from Jeff Stewart: NT opens stdin and stdout in text mode
+       by default, badly confusing our length calculations.  So we need
+       to set the file handle to binary. 
+    */
+    _setmode(_fileno(stdin), _O_BINARY); 
+#endif 
+    /* XXX - Puke if length is too big. */
+
+    /* Allocate our memory block. */
+    result = xmlrpc_mem_block_new(env, length);
+    XMLRPC_FAIL_IF_FAULT(env);
+    contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, result);
+
+    /* Get our data off the network.
+    ** XXX - Coercing 'size_t' to 'unsigned long' might be unsafe under
+    ** really weird circumstances. */
+    count = fread(contents, sizeof(char), length, stdin);
+    if (count < length)
+        XMLRPC_FAIL2(env, XMLRPC_INTERNAL_ERROR,
+                     "Expected %ld bytes, received %ld",
+                     (unsigned long) length, (unsigned long) count);
+
+ cleanup:
+    if (env->fault_occurred) {
+        if (result)
+            xmlrpc_mem_block_free(result);
+        return NULL;
+    }
+    return result;
+}
+
+
+
+void
+xmlrpc_server_cgi_process_call(xmlrpc_registry * const registryP) {
+/*----------------------------------------------------------------------------
+  Get the XML-RPC call from Standard Input and environment variables,
+  parse it, find the right method, call it, prepare an XML-RPC
+  response with the result, and write it to Standard Output.
+-----------------------------------------------------------------------------*/
+    xmlrpc_env env;
+    char *method, *type, *length_str;
+    int length;
+    xmlrpc_mem_block *input, *output;
+    char *input_data, *output_data;
+    size_t input_size, output_size;
+    int code;
+    char *message;
+
+    /* Error-handling preconditions. */
+    xmlrpc_env_init(&env);
+    input = output = NULL;
+
+    /* Set up a default error message. */
+    code = 500; message = "Internal Server Error";
+
+    /* Get our HTTP information from the environment. */
+    method = getenv("REQUEST_METHOD");
+    type = getenv("CONTENT_TYPE");
+    length_str = getenv("CONTENT_LENGTH");
+
+    /* Perform some sanity checks. */
+    if (!method || 0 != strcmp(method, "POST")) {
+        code = 405; message = "Method Not Allowed";
+        XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Expected HTTP method POST");
+    }
+    if (!type || 0 != strcmp(type, "text/xml")) {
+        code = 400; message = "Bad Request";
+        XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Expected text/xml content");
+    }
+    if (!length_str) {
+        code = 411; message = "Length Required";
+        XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Content-length required");
+    }
+
+    /* Get our content length. */
+    length = atoi(length_str);
+    if (length <= 0) {
+        code = 400; message = "Bad Request";
+        XMLRPC_FAIL(&env, XMLRPC_INTERNAL_ERROR, "Content-length must be > 0");
+    }
+
+    /* SECURITY: Make sure our content length is legal.
+    ** XXX - We can cast 'input_len' because we know it's >= 0, yes? */
+    if ((size_t) length > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) {
+        code = 400; message = "Bad Request";
+        XMLRPC_FAIL(&env, XMLRPC_LIMIT_EXCEEDED_ERROR,
+                    "XML-RPC request too large");
+    }
+
+    /* Get our body. */
+    input = get_body(&env, length);
+    XMLRPC_FAIL_IF_FAULT(&env);
+    input_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, input);
+    input_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input);
+
+    /* Process our call. */
+    output = xmlrpc_registry_process_call(&env, registryP, NULL,
+                                          input_data, input_size);
+    XMLRPC_FAIL_IF_FAULT(&env);
+    output_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output);
+    output_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
+
+    /* Send our data. */
+    send_xml(output_data, output_size);
+    
+ cleanup:
+    if (input)
+        xmlrpc_mem_block_free(input);
+    if (output)
+        xmlrpc_mem_block_free(output);
+    
+    if (env.fault_occurred)
+        send_error(code, message, &env);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+void
+xmlrpc_cgi_init(int const flags ATTR_UNUSED) {
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+    globalRegistryP = xmlrpc_registry_new(&env);
+    die_if_fault_occurred(&env);
+    xmlrpc_env_clean(&env);    
+}
+
+
+
+void
+xmlrpc_cgi_cleanup(void) {
+    xmlrpc_registry_free(globalRegistryP);
+}
+
+
+
+xmlrpc_registry *
+xmlrpc_cgi_registry(void) {
+    return globalRegistryP;
+}
+
+
+
+void
+xmlrpc_cgi_add_method(const char *  const method_name,
+                      xmlrpc_method const method,
+                      void *        const user_data) {
+    xmlrpc_env env;
+    xmlrpc_env_init(&env);
+    xmlrpc_registry_add_method(&env, globalRegistryP, NULL, method_name,
+                               method, user_data);
+    die_if_fault_occurred(&env);
+    xmlrpc_env_clean(&env);    
+}
+
+
+
+void
+xmlrpc_cgi_add_method_w_doc(const char *  const method_name,
+                            xmlrpc_method const method,
+                            void *        const user_data,
+                            const char *  const signature,
+                            const char *  const help) {
+    xmlrpc_env env;
+    xmlrpc_env_init(&env);
+    xmlrpc_registry_add_method_w_doc(&env, globalRegistryP, NULL, method_name,
+                                     method, user_data, signature, help);
+    die_if_fault_occurred(&env);
+    xmlrpc_env_clean(&env);    
+}
+
+
+
+void
+xmlrpc_cgi_process_call(void) {
+    
+    xmlrpc_server_cgi_process_call(globalRegistryP);
+}
diff --git a/src/xmlrpc_server_w32httpsys.c b/src/xmlrpc_server_w32httpsys.c
new file mode 100644 (file)
index 0000000..f899d1f
--- /dev/null
@@ -0,0 +1,924 @@
+/* Copyright (C) 2005 by Steven A. Bone, sbone@pobox.com. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+/* COMPILATION NOTE:
+   Note that the Platform SDK headers and
+   link libraries for Windows XP SP2 or newer are required to compile
+   xmlrpc-c for this module.  If you are not using this server, it is 
+   safe to exclude the xmlrpc_server_w32httpsys.c file from the xmlrpc
+   project and these dependencies will not be required.  You can get the 
+   latest platform SDK at 
+   http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
+   Be sure after installation to choose the program to "register the PSDK
+   directories with Visual Studio" so the newer headers are found.
+*/
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+
+#ifndef _UNICODE
+#define _UNICODE
+#endif
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/server.h"
+#include "xmlrpc-c/server_w32httpsys.h"
+#include "version.h"
+
+#if MUST_BUILD_HTTP_SYS_SERVER > 0
+
+/* See compilation note above if this header is not found! */
+#include <http.h>
+#include <windows.h>
+#include <strsafe.h>
+
+#pragma comment( lib, "httpapi" )
+
+
+/* XXX - This variable is *not* currently threadsafe. Once the server has
+** been started, it must be treated as read-only. */
+static xmlrpc_registry *global_registryP;
+
+//set TRUE if you want a log
+static BOOL g_bDebug;
+//set log filename
+static char g_fLogFile[MAX_PATH];
+//do you want OutputDebugString() to be called?
+static BOOL g_bDebugString;
+
+//
+// Macros.
+//
+#define INITIALIZE_HTTP_RESPONSE( resp, status, reason )                    \
+    do                                                                      \
+    {                                                                       \
+        RtlZeroMemory( (resp), sizeof(*(resp)) );                           \
+        (resp)->StatusCode = (status);                                      \
+        (resp)->pReason = (reason);                                         \
+        (resp)->ReasonLength = (USHORT) strlen(reason);                     \
+    } while (FALSE)
+
+
+#define ADD_KNOWN_HEADER(Response, HeaderId, RawValue)                      \
+    do                                                                      \
+    {                                                                       \
+        (Response).Headers.KnownHeaders[(HeaderId)].pRawValue = (RawValue); \
+        (Response).Headers.KnownHeaders[(HeaderId)].RawValueLength =        \
+            (USHORT) strlen(RawValue);                                      \
+    } while(FALSE)
+
+#define ALLOC_MEM(cb) HeapAlloc(GetProcessHeap(), 0, (cb))
+#define FREE_MEM(ptr) HeapFree(GetProcessHeap(), 0, (ptr))
+
+//
+// Prototypes for Internal Functions.
+//
+DWORD
+DoReceiveRequests(
+    HANDLE hReqQueue,
+       const xmlrpc_server_httpsys_parms * const parmsP
+    );
+
+DWORD
+SendHttpResponse(
+    IN HANDLE        hReqQueue,
+    IN PHTTP_REQUEST pRequest,
+    IN USHORT        StatusCode,
+    IN PSTR          pReason,
+    IN PSTR          pEntity
+    );
+
+DWORD
+SendHttpResponseAuthRequired(
+    IN HANDLE        hReqQueue,
+    IN PHTTP_REQUEST pRequest
+    );
+
+void
+processRPCCall(
+    xmlrpc_env *     const envP,
+    IN HANDLE        hReqQueue,
+    IN PHTTP_REQUEST pRequest
+    );
+
+__inline void TraceA(const char *format, ...);
+__inline void TraceW(const wchar_t *format, ...);
+
+
+//
+// External Function Implementation.
+//
+
+void
+xmlrpc_server_httpsys(
+       xmlrpc_env *                        const envP,
+    const xmlrpc_server_httpsys_parms * const parmsP,
+    unsigned int                        const parm_size
+       )
+{
+       ULONG           retCode;
+    HANDLE          hReqQueue      = NULL;
+    HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_1;
+       WCHAR           wszURL[35];
+
+       XMLRPC_ASSERT_ENV_OK(envP);
+
+    if (parm_size < XMLRPC_HSSIZE(authfn))
+       {
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INTERNAL_ERROR,
+            "You must specify members at least up through "
+            "'authfn' in the server parameters argument.  "
+            "That would mean the parameter size would be >= %u "
+            "but you specified a size of %u",
+            XMLRPC_HSSIZE(authfn), parm_size);
+               return;
+       }
+
+       //Set logging options
+       if (parmsP->logLevel>0)
+               g_bDebug=TRUE;
+       else
+               g_bDebug=FALSE;
+
+       if (parmsP->logLevel>1)
+               g_bDebugString=TRUE;
+       else
+               g_bDebugString=FALSE;
+
+       if (!parmsP->logFile)
+               g_bDebug=FALSE;
+       else
+               StringCchPrintfA(g_fLogFile,MAX_PATH,parmsP->logFile);
+
+       //construct the URL we are listening on
+       if (parmsP->useSSL!=0)
+               StringCchPrintf(wszURL,35,L"https://+:%u/RPC2",parmsP->portNum);
+       else
+               StringCchPrintf(wszURL,35,L"http://+:%u/RPC2",parmsP->portNum);
+
+       global_registryP = parmsP->registryP;
+
+       // Initialize HTTP APIs.
+       retCode = HttpInitialize( 
+                               HttpApiVersion,
+                               HTTP_INITIALIZE_SERVER,    // Flags
+                               NULL                       // Reserved
+                               );
+       if (retCode != NO_ERROR)
+       {
+               xmlrpc_env_set_fault_formatted(
+                       envP, XMLRPC_INTERNAL_ERROR,
+                       "HttpInitialize failed with %lu \n ",
+                       retCode);
+               return;
+       }
+
+       // Create a Request Queue Handle
+       retCode = HttpCreateHttpHandle(
+                               &hReqQueue,        // Req Queue
+                               0                  // Reserved
+                               );
+       if (retCode != NO_ERROR)
+       { 
+               xmlrpc_env_set_fault_formatted(
+                       envP, XMLRPC_INTERNAL_ERROR,
+                       "HttpCreateHttpHandle failed with %lu \n ",
+                       retCode);
+               goto CleanUp;
+       }
+
+       retCode = HttpAddUrl(
+                               hReqQueue,    // Req Queue
+                               wszURL,      // Fully qualified URL
+                               NULL          // Reserved
+                               );
+
+       if (retCode != NO_ERROR)
+       {
+               xmlrpc_env_set_fault_formatted(
+                       envP, XMLRPC_INTERNAL_ERROR,
+                       "HttpAddUrl failed with %lu \n ",
+                       retCode);
+               goto CleanUp;
+       }
+
+       TraceW( L"we are listening for requests on the following url: %ws\n", wszURL);
+
+       // Loop while receiving requests
+       for(;;)
+       {
+               TraceW( L"Calling DoReceiveRequests()\n");
+               retCode = DoReceiveRequests(hReqQueue, parmsP);
+               if(NO_ERROR == retCode)
+               {
+                       TraceW( L"DoReceiveRequests() returned NO_ERROR, breaking");
+                       break;
+               }
+       }
+
+CleanUp:
+
+       TraceW( L"Tearing down the server.\n", wszURL);
+
+       // Call HttpRemoveUrl for the URL that we added.
+       HttpRemoveUrl( hReqQueue, wszURL );
+
+       // Close the Request Queue handle.
+       if(hReqQueue)
+               CloseHandle(hReqQueue);
+
+       // Call HttpTerminate.
+       HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
+       return;
+}
+
+//
+// Internal Function Implementations.
+//
+
+__inline void TraceA(const char *format, ...)
+{
+       if(g_bDebug)
+       {
+               if (format)
+               {
+                       va_list arglist;
+                       char str[4096];
+
+                       va_start(arglist, format);
+                       if (g_fLogFile)
+                       {
+                               FILE *fout = fopen(g_fLogFile, "a+t");
+                               if (fout)
+                               {
+                                       vfprintf(fout, format, arglist);
+                                       fclose(fout);
+                               }
+                       }
+
+                       StringCchVPrintfA(str,4096, format, arglist);
+                       printf(str);
+
+                       if (g_bDebugString)
+                       {
+                               
+                               OutputDebugStringA(str);
+                       }
+
+                       va_end(arglist);
+               }
+       }
+}
+
+__inline void TraceW(const wchar_t *format, ...)
+{
+       if(g_bDebug)
+       {
+               if (format)
+               {
+                       va_list arglist;
+                       wchar_t str[4096];
+
+                       va_start(arglist, format);
+                       if (g_fLogFile)
+                       {
+                               FILE *fout = fopen(g_fLogFile, "a+t");
+                               if (fout)
+                               {
+                                       vfwprintf(fout, format, arglist);
+                                       fclose(fout);
+                               }
+                       }
+                       
+                       StringCchVPrintfW(str, 4096, format, arglist);
+                       wprintf(str);
+                       
+                       if (g_bDebugString)
+                       {                               
+                               OutputDebugStringW(str);
+                       }
+
+                       va_end(arglist);
+               }
+       }
+}
+
+/*
+ * This is a blocking function that merely sits on the request queue
+ * for our URI and processes them one at a time.  Once a request comes
+ * in, we check it for content-type, content-length, and verb.  As long
+ * as the initial validations are done, we pass the request to the 
+ * processRPCCall() function, which collects the body of the request
+ * and processes it.  If we get an error back other than network type,
+ * we are responsible for notifing the client.
+ */
+DWORD
+DoReceiveRequests(
+    IN HANDLE hReqQueue,
+       const xmlrpc_server_httpsys_parms * const parmsP
+    )
+{
+    ULONG              result;
+    HTTP_REQUEST_ID    requestId;
+    DWORD              bytesRead;
+    PHTTP_REQUEST      pRequest;
+    PCHAR              pRequestBuffer;
+    ULONG              RequestBufferLength;
+       xmlrpc_env                      env;
+       char                            szHeaderBuf[255];
+       long                            lContentLength;
+
+    // Allocate a 2K buffer. Should be good for most requests, we'll grow 
+    // this if required. We also need space for a HTTP_REQUEST structure.
+    RequestBufferLength = sizeof(HTTP_REQUEST) + 2048;
+    pRequestBuffer      = (PCHAR) ALLOC_MEM( RequestBufferLength );
+    if (pRequestBuffer == NULL)
+    {
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    pRequest = (PHTTP_REQUEST)pRequestBuffer;
+
+    // Wait for a new request -- This is indicated by a NULL request ID.
+    HTTP_SET_NULL_ID( &requestId );
+    for(;;)
+    {
+        RtlZeroMemory(pRequest, RequestBufferLength);
+
+        result = HttpReceiveHttpRequest(
+                    hReqQueue,          // Req Queue
+                    requestId,          // Req ID
+                    0,                  // Flags
+                    pRequest,           // HTTP request buffer
+                    RequestBufferLength,// req buffer length
+                    &bytesRead,         // bytes received
+                    NULL                // LPOVERLAPPED
+                    );
+
+        if(NO_ERROR == result)
+        {
+            // Got a request with a filled buffer.
+            switch(pRequest->Verb)
+            {
+                case HttpVerbPOST:
+
+                                       TraceW(L"Got a POST request for %ws \n",pRequest->CookedUrl.pFullUrl);                          
+                                       
+                                       //Check if we need use authorization.
+                                       if(parmsP->authfn)
+                                       {
+                                               xmlrpc_env_init(&env);
+                                               if(pRequest->Headers.KnownHeaders[HttpHeaderAuthorization].RawValueLength<6)
+                                               {
+                                                       xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR, 
+                                                               "Authorization header too short.");
+                                               }
+                                               else
+                                               {
+                                                       //unencode the headers
+                                                       if(_strnicmp("basic ",pRequest->Headers.KnownHeaders[HttpHeaderAuthorization].pRawValue,6)!=0)
+                                                       {
+                                                               xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR, 
+                                                                       "Authorization header is not of type basic.");
+                                                       }
+                                                       else
+                                                       {
+                                                               xmlrpc_mem_block * decoded;
+                                                               
+                                                               decoded = xmlrpc_base64_decode(&env,pRequest->Headers.KnownHeaders[HttpHeaderAuthorization].pRawValue+6,pRequest->Headers.KnownHeaders[HttpHeaderAuthorization].RawValueLength-6);
+                                                               if(!env.fault_occurred)
+                                                               {
+                                                                       char *pDecodedStr;
+                                                                       char *pUser;
+                                                                       char *pPass;
+                                                                       char *pColon;
+
+                                                                       pDecodedStr = (char*)malloc(decoded->_size+1);
+                                                                       memcpy(pDecodedStr,decoded->_block,decoded->_size);
+                                                                       pDecodedStr[decoded->_size]='\0';
+                                                                       pUser = pPass = pDecodedStr;
+                                                                       pColon=strchr(pDecodedStr,':');
+                                                                       if(pColon)
+                                                                       {
+                                                                               *pColon='\0';
+                                                                               pPass=pColon+1;
+                                                                               //The authfn should set env to fail if auth is denied.
+                                                                               parmsP->authfn(&env,pUser,pPass);
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               xmlrpc_env_set_fault( &env, XMLRPC_REQUEST_REFUSED_ERROR, 
+                                                                                       "Decoded auth not of the correct format.");
+                                                                       }
+                                                                       free(pDecodedStr);
+                                                               }
+                                                               if(decoded)
+                                                                       XMLRPC_MEMBLOCK_FREE(char, decoded);
+                                                       }
+                                               }
+                                               if(env.fault_occurred)
+                                               {
+                                                       //request basic authorization, as the user did not provide it.
+                                                       xmlrpc_env_clean(&env);
+                                                       TraceW(L"POST request did not provide valid authorization header.");
+                                                       result = SendHttpResponseAuthRequired( hReqQueue, pRequest);
+                                                       break;
+                                               }
+                                               xmlrpc_env_clean(&env);
+                                       }
+                                       
+                                       //Check content type to make sure it is text/xml.
+                                       memcpy(szHeaderBuf,pRequest->Headers.KnownHeaders[HttpHeaderContentType].pRawValue,pRequest->Headers.KnownHeaders[HttpHeaderContentType].RawValueLength);
+                                       szHeaderBuf[pRequest->Headers.KnownHeaders[HttpHeaderContentType].RawValueLength]='\0';
+                                       if (_stricmp(szHeaderBuf,"text/xml")!=0)
+                                       {
+                                               //We only handle text/xml data.  Anything else is not valid.
+                                               TraceW(L"POST request had an unsupported content-type: %s \n", szHeaderBuf);
+                                               result = SendHttpResponse(
+                                                                       hReqQueue, 
+                                                                       pRequest,
+                                                                       400,
+                                                                       "Bad Request",
+                                                                       NULL
+                                                                       );
+                                               break;
+                                       }
+
+                                       //Check content length to make sure it exists and is not too big.
+                                       memcpy(szHeaderBuf,pRequest->Headers.KnownHeaders[HttpHeaderContentLength].pRawValue,pRequest->Headers.KnownHeaders[HttpHeaderContentLength].RawValueLength);
+                                       szHeaderBuf[pRequest->Headers.KnownHeaders[HttpHeaderContentLength].RawValueLength]='\0';
+                                       lContentLength = atol(szHeaderBuf);
+                                       if (lContentLength<=0)
+                                       {
+                                               //Make sure a content length was supplied.
+                                               TraceW(L"POST request did not include a content-length \n", szHeaderBuf);
+                                               result = SendHttpResponse(
+                                                                       hReqQueue, 
+                                                                       pRequest,
+                                                                       411,
+                                                                       "Length Required",
+                                                                       NULL
+                                                                       );
+                                               break;
+                                       }                                               
+                                       if((size_t) lContentLength > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
+                                       {
+                                               //Content-length is too big for us to handle
+                                               TraceW(L"POST request content-length is too big for us to handle: %d bytes \n", lContentLength);
+                                               result = SendHttpResponse(
+                                                                       hReqQueue, 
+                                                                       pRequest,
+                                                                       500,
+                                                                       "content-length too large",
+                                                                       NULL
+                                                                       );
+                                               break;
+                                       }
+
+                                       //our initial validations of POST, content-type, and content-length
+                                       //all check out.  Collect and pass the complete buffer to the 
+                                       //XMLRPC-C library
+                                       
+                                       xmlrpc_env_init(&env);
+                    processRPCCall(&env,hReqQueue, pRequest);
+                                       if (env.fault_occurred) 
+                                       {
+                                               //if we fail and it is anything other than a network error,
+                                               //we should return a failure response to the client.
+                                               if (env.fault_code != XMLRPC_NETWORK_ERROR)
+                                               {
+                                                       if (env.fault_string)
+                                                               result = SendHttpResponse(
+                                                                       hReqQueue, 
+                                                                       pRequest,
+                                                                       500,
+                                                                       env.fault_string,
+                                                                       NULL
+                                                                       );
+                                                       else
+                                                               result = SendHttpResponse(
+                                                                       hReqQueue, 
+                                                                       pRequest,
+                                                                       500,
+                                                                       "Unknown Error",
+                                                                       NULL
+                                                                       );
+                                               }
+                                       }
+                                       
+                                       xmlrpc_env_clean(&env);
+                    break;
+
+                default:
+                                       //We only handle POST data.  Anything else is not valid.
+                    TraceW(L"Got an unsupported Verb request for URI %ws \n", pRequest->CookedUrl.pFullUrl);
+                       
+                    result = SendHttpResponse(
+                                hReqQueue, 
+                                pRequest,
+                                405,
+                                "Method Not Allowed",
+                                NULL
+                                );
+                    break;
+            }
+            if(result != NO_ERROR)
+            {
+                break;
+            }
+
+            // Reset the Request ID so that we pick up the next request.
+            HTTP_SET_NULL_ID( &requestId );
+        }
+        else if(result == ERROR_MORE_DATA)
+        {
+            // The input buffer was too small to hold the request headers
+            // We have to allocate more buffer & call the API again. 
+            //
+            // When we call the API again, we want to pick up the request
+            // that just failed. This is done by passing a RequestID.
+            // This RequestID is picked from the old buffer.
+            requestId = pRequest->RequestId;
+
+            // Free the old buffer and allocate a new one.
+            RequestBufferLength = bytesRead;
+            FREE_MEM( pRequestBuffer );
+            pRequestBuffer = (PCHAR) ALLOC_MEM( RequestBufferLength );
+
+            if (pRequestBuffer == NULL)
+            {
+                result = ERROR_NOT_ENOUGH_MEMORY;
+                break;
+            }
+
+            pRequest = (PHTTP_REQUEST)pRequestBuffer;
+
+        }
+        else if(ERROR_CONNECTION_INVALID == result && 
+                !HTTP_IS_NULL_ID(&requestId))
+        {
+            // The TCP connection got torn down by the peer when we were
+            // trying to pick up a request with more buffer. We'll just move
+            // onto the next request.            
+            HTTP_SET_NULL_ID( &requestId );
+        }
+        else
+        {
+            break;
+        }
+
+    } // for(;;)
+Cleanup:
+
+    if(pRequestBuffer)
+    {
+        FREE_MEM( pRequestBuffer );
+    }
+
+    return result;
+}
+
+/*
+ * SendHttpResponse sends a text/html content type back with
+ * the user specified status code and reason.  Used for returning
+ * errors to clients.
+ */
+DWORD
+SendHttpResponse(
+    IN HANDLE        hReqQueue,
+    IN PHTTP_REQUEST pRequest,
+    IN USHORT        StatusCode,
+    IN PSTR          pReason,
+    IN PSTR          pEntityString
+    )
+{
+    HTTP_RESPONSE   response;
+    HTTP_DATA_CHUNK dataChunk;
+    DWORD           result;
+    DWORD           bytesSent;
+       CHAR                    szServerHeader[20];
+
+    // Initialize the HTTP response structure.
+    INITIALIZE_HTTP_RESPONSE(&response, StatusCode, pReason);
+
+    ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html");
+       
+       StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION);                                    
+       ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader);
+   
+    if(pEntityString)
+    {
+        // Add an entity chunk
+        dataChunk.DataChunkType           = HttpDataChunkFromMemory;
+        dataChunk.FromMemory.pBuffer      = pEntityString;
+        dataChunk.FromMemory.BufferLength = (ULONG) strlen(pEntityString);
+
+        response.EntityChunkCount         = 1;
+        response.pEntityChunks            = &dataChunk;
+    }
+
+    // Since we are sending all the entity body in one call, we don't have 
+    // to specify the Content-Length.
+    result = HttpSendHttpResponse(
+                    hReqQueue,           // ReqQueueHandle
+                    pRequest->RequestId, // Request ID
+                    0,                   // Flags
+                    &response,           // HTTP response
+                    NULL,                // pReserved1
+                    &bytesSent,          // bytes sent   (OPTIONAL)
+                    NULL,                // pReserved2   (must be NULL)
+                    0,                   // Reserved3    (must be 0)
+                    NULL,                // LPOVERLAPPED (OPTIONAL)
+                    NULL                 // pReserved4   (must be NULL)
+                    );
+
+    if(result != NO_ERROR)
+    {
+               TraceW(L"HttpSendHttpResponse failed with %lu \n", result);
+    }
+
+    return result;
+}
+
+/*
+ * SendHttpResponseAuthRequired sends a 401 status code requesting authorization
+ */
+DWORD
+SendHttpResponseAuthRequired(
+    IN HANDLE        hReqQueue,
+    IN PHTTP_REQUEST pRequest
+    )
+{
+    HTTP_RESPONSE   response;
+    DWORD           result;
+    DWORD           bytesSent;
+       CHAR                    szServerHeader[20];
+
+    // Initialize the HTTP response structure.
+    INITIALIZE_HTTP_RESPONSE(&response, 401, "Authentication Required");
+
+    // Add the WWW_Authenticate header.
+    ADD_KNOWN_HEADER(response, HttpHeaderWwwAuthenticate, "Basic realm=\"xmlrpc\"");
+       
+       StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION);                                    
+       ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader);
+   
+    // Since we are sending all the entity body in one call, we don't have 
+    // to specify the Content-Length.
+    result = HttpSendHttpResponse(
+                    hReqQueue,           // ReqQueueHandle
+                    pRequest->RequestId, // Request ID
+                    0,                   // Flags
+                    &response,           // HTTP response
+                    NULL,                // pReserved1
+                    &bytesSent,          // bytes sent   (OPTIONAL)
+                    NULL,                // pReserved2   (must be NULL)
+                    0,                   // Reserved3    (must be 0)
+                    NULL,                // LPOVERLAPPED (OPTIONAL)
+                    NULL                 // pReserved4   (must be NULL)
+                    );
+
+    if(result != NO_ERROR)
+    {
+               TraceW(L"SendHttpResponseAuthRequired failed with %lu \n", result);
+    }
+
+    return result;
+}
+
+/*
+ * processRPCCall() is called after some validations.  The assumption is that
+ * the request is an HTTP post of content-type text/xml with a content-length
+ * that is less than the maximum the library can handle.
+ *
+ * The caller should check the error status, and if the error was other than
+ * a network type, respond back to the client to let them know the call failed.
+ */
+void
+processRPCCall(
+    xmlrpc_env *     const envP,
+    IN HANDLE        hReqQueue,
+    IN PHTTP_REQUEST pRequest
+    )
+{
+    HTTP_RESPONSE   response;
+    DWORD           result;
+    DWORD           bytesSent;
+    PUCHAR          pEntityBuffer;
+    ULONG           EntityBufferLength;
+    ULONG           BytesRead;
+#define MAX_ULONG_STR ((ULONG) sizeof("4294967295"))
+    CHAR            szContentLength[MAX_ULONG_STR];
+       CHAR                    szServerHeader[20];
+    HTTP_DATA_CHUNK dataChunk;
+    ULONG           TotalBytesRead = 0;
+       xmlrpc_mem_block * body;
+       xmlrpc_mem_block * output;
+
+    BytesRead  = 0;
+       body       = NULL;
+       output     = NULL;
+
+    // Allocate some space for an entity buffer.
+    EntityBufferLength = 2048; 
+    pEntityBuffer      = (PUCHAR) ALLOC_MEM( EntityBufferLength );
+    if (pEntityBuffer == NULL)
+    {
+               xmlrpc_env_set_fault_formatted(
+                               envP, XMLRPC_INTERNAL_ERROR,
+                               "Out of Memory");
+        goto Done;
+    }
+
+       // NOTE: If we had passed the HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
+    //       flag with HttpReceiveHttpRequest(), the entity would have
+    //       been a part of HTTP_REQUEST (using the pEntityChunks field).
+    //       Since we have not passed that flag, we can be assured that 
+    //       there are no entity bodies in HTTP_REQUEST.
+    if(pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS)
+    {
+               //Allocate some space for an XMLRPC memory block.
+               body = xmlrpc_mem_block_new(envP, 0);
+               if (envP->fault_occurred) 
+                       goto Done;
+
+        // The entity body can be sent over multiple calls. Let's collect all
+        // of these in a buffer and send the buffer to the xmlrpc-c library 
+        do
+        {
+            // Read the entity chunk from the request.
+            BytesRead = 0; 
+            result = HttpReceiveRequestEntityBody(
+                        hReqQueue,
+                        pRequest->RequestId,
+                        0,
+                        pEntityBuffer,
+                        EntityBufferLength,
+                        &BytesRead,
+                        NULL
+                        );
+            switch(result)
+            {
+                case NO_ERROR:
+                    if(BytesRead != 0)
+                    {
+                                               XMLRPC_TYPED_MEM_BLOCK_APPEND(char, envP, body, 
+                                          pEntityBuffer, BytesRead);
+                                               if(envP->fault_occurred)
+                                                       goto Done;                                              
+                    }
+                    break;
+
+                case ERROR_HANDLE_EOF:
+                    // We have read the last request entity body. We can now 
+                    // process the suppossed XMLRPC data.
+                    if(BytesRead != 0)
+                    {
+                                               XMLRPC_TYPED_MEM_BLOCK_APPEND(char, envP, body, 
+                                          pEntityBuffer, BytesRead);
+                                               if(envP->fault_occurred)
+                                                       goto Done;
+                    }
+
+                    // We will send the response over multiple calls. 
+                                       // This is achieved by passing the 
+                    // HTTP_SEND_RESPONSE_FLAG_MORE_DATA flag.
+                    
+                    // NOTE: Since we are accumulating the TotalBytesRead in 
+                    //       a ULONG, this will not work for entity bodies that
+                    //       are larger than 4 GB. For supporting large entity
+                    //       bodies, we would have to use a ULONGLONG.
+                                       TraceA("xmlrpc_server RPC2 handler processing RPC request.\n");
+                                                                               
+                                       // Process the RPC.
+                                       output = xmlrpc_registry_process_call(
+                                                                               envP, global_registryP, NULL, 
+                                                                               XMLRPC_MEMBLOCK_CONTENTS(char, body),
+                                                                               XMLRPC_MEMBLOCK_SIZE(char, body));
+                                       if (envP->fault_occurred) 
+                                               goto Done;
+
+                                       // Initialize the HTTP response structure.
+                                       INITIALIZE_HTTP_RESPONSE(&response, 200, "OK");
+
+                                       //Add the content-length
+                                       StringCchPrintfA(szContentLength,MAX_ULONG_STR, "%lu",
+                                                                               XMLRPC_MEMBLOCK_SIZE(char, output));
+                                       ADD_KNOWN_HEADER(
+                                                       response, 
+                                                       HttpHeaderContentLength, 
+                                                       szContentLength );
+
+                                       //Add the content-type
+                                       ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/xml");
+                                       
+                                       StringCchPrintfA(szServerHeader,20, "xmlrpc-c %s",XMLRPC_C_VERSION);                                    
+                                       ADD_KNOWN_HEADER(response, HttpHeaderServer, szServerHeader);
+
+                                       //send the response
+                                       result = HttpSendHttpResponse(
+                                                       hReqQueue,           // ReqQueueHandle
+                                                       pRequest->RequestId, // Request ID
+                                                       HTTP_SEND_RESPONSE_FLAG_MORE_DATA,
+                                                       &response,           // HTTP response
+                                                       NULL,                // pReserved1
+                                                       &bytesSent,          // bytes sent (optional)
+                                                       NULL,                // pReserved2
+                                                       0,                   // Reserved3
+                                                       NULL,                // LPOVERLAPPED
+                                                       NULL                 // pReserved4
+                                                       );
+                                       if(result != NO_ERROR)
+                                       {
+                                               TraceW(L"HttpSendHttpResponse failed with %lu \n", result);
+                                               xmlrpc_env_set_fault_formatted(
+                                                       envP, XMLRPC_NETWORK_ERROR,
+                                                       "HttpSendHttpResponse failed with %lu", result);
+                                               goto Done;
+                                       }
+
+                                       // Send entity body from a memory chunk.
+                                       dataChunk.DataChunkType = HttpDataChunkFromMemory;
+                                       dataChunk.FromMemory.BufferLength = (ULONG)XMLRPC_MEMBLOCK_SIZE(char, output);
+                                       dataChunk.FromMemory.pBuffer = XMLRPC_MEMBLOCK_CONTENTS(char, output);
+
+                                       result = HttpSendResponseEntityBody(
+                                                               hReqQueue,
+                                                               pRequest->RequestId,
+                                                               0,                    // This is the last send.
+                                                               1,                    // Entity Chunk Count.
+                                                               &dataChunk,
+                                                               NULL,
+                                                               NULL,
+                                                               0,
+                                                               NULL,
+                                                               NULL
+                                                               );
+                                       if(result != NO_ERROR)
+                                       {
+                                               TraceW(L"HttpSendResponseEntityBody failed with %lu \n", result);
+                                               xmlrpc_env_set_fault_formatted(
+                                                               envP, XMLRPC_NETWORK_ERROR,
+                                                               "HttpSendResponseEntityBody failed with %lu", result);
+                                               goto Done;
+                                       }
+                                       goto Done;
+                    break;
+                default:
+                                       TraceW(L"HttpReceiveRequestEntityBody failed with %lu \n", result);
+                                       xmlrpc_env_set_fault_formatted(
+                                                               envP, XMLRPC_NETWORK_ERROR,
+                                                               "HttpReceiveRequestEntityBody failed with %lu", result);
+                    goto Done;
+            }
+        } while(TRUE);
+    }
+    else
+    {
+               // This request does not have an entity body. 
+               TraceA("Received a bad request (no body in HTTP post).\n");
+               xmlrpc_env_set_fault_formatted(
+                               envP, XMLRPC_PARSE_ERROR,
+                               "Bad POST request (no body)");
+        goto Done;
+    }
+
+Done:
+
+    if(pEntityBuffer)
+        FREE_MEM(pEntityBuffer);
+
+       if(output)
+               XMLRPC_MEMBLOCK_FREE(char, output);
+
+       if(body)
+               XMLRPC_MEMBLOCK_FREE(char, body);
+
+    return;
+}
+
+#endif /* #if MUST_BUILD_HTTP_SYS_SERVER <> 0 */
\ No newline at end of file
diff --git a/src/xmlrpc_struct.c b/src/xmlrpc_struct.c
new file mode 100644 (file)
index 0000000..7fabb04
--- /dev/null
@@ -0,0 +1,610 @@
+/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+#include "xmlrpc_config.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/base_int.h"
+
+#define KEY_ERROR_BUFFER_SZ (32)
+
+
+void
+xmlrpc_destroyStruct(xmlrpc_value * const structP) {
+
+    _struct_member * const members = 
+        XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
+    size_t const size = 
+        XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block);
+
+    unsigned int i;
+
+    for (i = 0; i < size; ++i) {
+        xmlrpc_DECREF(members[i].key);
+        xmlrpc_DECREF(members[i].value);
+    }
+    XMLRPC_MEMBLOCK_CLEAN(_struct_member, &structP->_block);
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_struct_new
+**=========================================================================
+**  Create a new <struct> value. The corresponding destructor code
+**  currently lives in xmlrpc_DECREF.
+**
+**  We store the individual members in an array of _struct_member. This
+**  contains a key, a hash code, and a value. We look up keys by doing
+**  a linear search of the hash codes.
+*/
+
+xmlrpc_value *
+xmlrpc_struct_new(xmlrpc_env * const envP) {
+
+    xmlrpc_value * valP;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+
+    xmlrpc_createXmlrpcValue(envP, &valP);
+    if (!envP->fault_occurred) {
+        valP->_type = XMLRPC_TYPE_STRUCT;
+
+        XMLRPC_MEMBLOCK_INIT(_struct_member, envP, &valP->_block, 0);
+
+        if (envP->fault_occurred)
+            free(valP);
+    }
+    return valP;
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_struct_size
+**=========================================================================
+**  Return the number of key-value pairs contained in the struct. If the
+**  value is not a struct, return -1 and set a fault.
+*/
+
+int 
+xmlrpc_struct_size(xmlrpc_env* env, xmlrpc_value* strct)
+{
+    int retval;
+
+    /* Suppress a compiler warning about uninitialized variables. */
+    retval = 0;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_VALUE_OK(strct);
+
+    XMLRPC_TYPE_CHECK(env, strct, XMLRPC_TYPE_STRUCT);
+    retval = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strct->_block);
+
+ cleanup:
+    if (env->fault_occurred)
+        return -1;
+    return retval;
+}
+
+
+
+/*=========================================================================
+**  get_hash
+**=========================================================================
+**  A mindlessly simple hash function. Please feel free to write something
+**  more clever if this produces bad results.
+*/
+
+static unsigned char 
+get_hash(const char * const key, 
+         size_t       const key_len) {
+
+    unsigned char retval;
+    size_t i;
+
+    XMLRPC_ASSERT(key != NULL);
+    
+    retval = 0;
+    for (i = 0; i < key_len; i++)
+        retval += key[i];
+    return retval;
+}
+
+
+
+/*=========================================================================
+**  find_member
+**=========================================================================
+**  Get the index of the member with the specified key, or -1 if no such
+**  member exists.
+*/
+
+static int 
+find_member(xmlrpc_value * const strctP, 
+            const char *   const key, 
+            size_t         const key_len) {
+
+    size_t size, i;
+    unsigned char hash;
+    _struct_member *contents;
+    xmlrpc_value *keyval;
+    char *keystr;
+    size_t keystr_size;
+
+    XMLRPC_ASSERT_VALUE_OK(strctP);
+    XMLRPC_ASSERT(key != NULL);
+
+    /* Look for our key. */
+    hash = get_hash(key, key_len);
+    size = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strctP->_block);
+    contents = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block);
+    for (i = 0; i < size; i++) {
+        if (contents[i].key_hash == hash) {
+            keyval = contents[i].key;
+            keystr = XMLRPC_MEMBLOCK_CONTENTS(char, &keyval->_block);
+            keystr_size = XMLRPC_MEMBLOCK_SIZE(char, &keyval->_block)-1;
+            if (key_len == keystr_size && memcmp(key, keystr, key_len) == 0)
+                return i;
+        }   
+    }
+    return -1;
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_struct_has_key
+**=========================================================================
+*/
+
+int 
+xmlrpc_struct_has_key(xmlrpc_env *   const envP,
+                      xmlrpc_value * const strctP,
+                      const char *   const key) {
+
+    XMLRPC_ASSERT(key != NULL);
+    return xmlrpc_struct_has_key_n(envP, strctP, key, strlen(key));
+}
+
+
+
+int 
+xmlrpc_struct_has_key_n(xmlrpc_env   * const envP,
+                        xmlrpc_value * const strctP,
+                        const char *   const key, 
+                        size_t         const key_len) {
+    int index;
+
+    /* Suppress a compiler warning about uninitialized variables. */
+    index = 0;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(strctP);
+    XMLRPC_ASSERT(key != NULL);
+    
+    XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
+    index = find_member(strctP, key, key_len);
+
+ cleanup:
+    if (envP->fault_occurred)
+        return 0;
+    return (index >= 0);
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_struct_find_value...
+**=========================================================================
+**  These functions look up a specified key value in a specified struct.
+**  If it exists, they return the value of the struct member.  If not,
+**  they return a NULL to indicate such.
+*/
+
+/* It would be a nice extension to be able to look up a key that is
+   not a text string.
+*/
+
+void
+xmlrpc_struct_find_value(xmlrpc_env *    const envP,
+                         xmlrpc_value *  const structP,
+                         const char *    const key,
+                         xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+  Given a key, retrieve a value from the struct.  If the key is not
+  present, return NULL as *valuePP.
+-----------------------------------------------------------------------------*/
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(structP);
+    XMLRPC_ASSERT_PTR_OK(key);
+    
+    if (structP->_type != XMLRPC_TYPE_STRUCT)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TYPE_ERROR, "Value is not a struct.  It is type #%d",
+            structP->_type);
+    else {
+        int index;
+
+        /* Get our member index. */
+        index = find_member(structP, key, strlen(key));
+        if (index < 0)
+            *valuePP = NULL;
+        else {
+            _struct_member * const members =
+                XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
+            *valuePP = members[index].value;
+            
+            XMLRPC_ASSERT_VALUE_OK(*valuePP);
+            
+            xmlrpc_INCREF(*valuePP);
+        }
+    }
+}
+
+
+
+static void
+findValueVNoRef(xmlrpc_env *    const envP,
+                xmlrpc_value *  const structP,
+                xmlrpc_value *  const keyP,
+                xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+  Same as xmlrpc_find_value_v(), except we don't increment the reference
+  count on the xmlrpc_value we return.
+-----------------------------------------------------------------------------*/
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(structP);
+    XMLRPC_ASSERT_VALUE_OK(keyP);
+    
+    if (structP->_type != XMLRPC_TYPE_STRUCT)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TYPE_ERROR, "Value is not a struct.  It is type #%d",
+            structP->_type);
+    else {
+        if (keyP->_type != XMLRPC_TYPE_STRING)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_TYPE_ERROR, "Key value is not a string.  "
+                "It is type #%d",
+                keyP->_type);
+        else {
+            int index;
+
+            /* Get our member index. */
+            index = find_member(structP, 
+                                XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block),
+                                XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block)-1);
+            if (index < 0)
+                *valuePP = NULL;
+            else {
+                _struct_member * const members =
+                    XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
+                *valuePP = members[index].value;
+                
+                XMLRPC_ASSERT_VALUE_OK(*valuePP);
+            }
+        }
+    }
+}
+
+
+
+void
+xmlrpc_struct_find_value_v(xmlrpc_env *    const envP,
+                           xmlrpc_value *  const structP,
+                           xmlrpc_value *  const keyP,
+                           xmlrpc_value ** const valuePP) {
+/*----------------------------------------------------------------------------
+  Given a key, retrieve a value from the struct.  If the key is not
+  present, return NULL as *valuePP.
+-----------------------------------------------------------------------------*/
+    findValueVNoRef(envP, structP, keyP, valuePP);
+
+    if (!envP->fault_occurred && *valuePP)
+        xmlrpc_INCREF(*valuePP);
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_struct_read_value...
+**=========================================================================
+**  These fail if no member with the specified key exists.
+**  Otherwise, they are the same as xmlrpc_struct_find_value...
+*/
+
+void
+xmlrpc_struct_read_value_v(xmlrpc_env *    const envP,
+                           xmlrpc_value *  const structP,
+                           xmlrpc_value *  const keyP,
+                           xmlrpc_value ** const valuePP) {
+
+    xmlrpc_struct_find_value_v(envP, structP, keyP, valuePP);
+
+    if (!envP->fault_occurred) {
+        if (*valuePP == NULL) {
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%.*s'",
+                (int)XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block),
+                XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block));
+        }
+    }
+}
+
+
+
+void
+xmlrpc_struct_read_value(xmlrpc_env *    const envP,
+                         xmlrpc_value *  const structP,
+                         const char *    const key,
+                         xmlrpc_value ** const valuePP) {
+
+    xmlrpc_struct_find_value(envP, structP, key, valuePP);
+    
+    if (!envP->fault_occurred) {
+        if (*valuePP == NULL) {
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%s'",
+                key);
+            /* We should fix the error message to format the key for display */
+        }
+    }
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_struct_get_value...
+**=========================================================================
+**  These are for backward compatibility.  They used to be the only ones.
+**  They're deprecated because they don't acquire a reference to the
+**  value they return.
+*/
+
+xmlrpc_value * 
+xmlrpc_struct_get_value_n(xmlrpc_env *   const envP,
+                          xmlrpc_value * const structP,
+                          const char *   const key, 
+                          size_t         const keyLen) {
+
+    xmlrpc_value * retval;
+    xmlrpc_value * keyP;
+    
+    keyP = xmlrpc_build_value(envP, "s#", key, keyLen);
+    if (!envP->fault_occurred) {
+        /* We cannot use xmlrpc_find_value_v here because 
+           some legacy code uses xmlrpc_struct_get_value() from multiple
+           simultaneous threads and xmlrpc_find_value isn't thread safe
+           due to its manipulation of the reference count.
+        */
+        findValueVNoRef(envP, structP, keyP, &retval);
+
+        if (!envP->fault_occurred) {
+            if (retval == NULL) {
+                xmlrpc_env_set_fault_formatted(
+                    envP, XMLRPC_INDEX_ERROR, 
+                    "No member of struct has key '%.*s'",
+                    (int)keyLen, key);
+                /* We should fix the error message to format the key
+                   for display */
+            }
+        }
+        xmlrpc_DECREF(keyP);
+    }
+    return retval;
+}
+
+
+
+xmlrpc_value * 
+xmlrpc_struct_get_value(xmlrpc_env *   const envP,
+                        xmlrpc_value * const strctP,
+                        const char *   const key) {
+
+    XMLRPC_ASSERT(key != NULL);
+    return xmlrpc_struct_get_value_n(envP, strctP, key, strlen(key));
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_struct_set_value
+**=========================================================================
+*/
+
+void 
+xmlrpc_struct_set_value(xmlrpc_env *   const envP,
+                        xmlrpc_value * const strctP,
+                        const char *   const key,
+                        xmlrpc_value * const valueP) {
+
+    XMLRPC_ASSERT(key != NULL);
+    xmlrpc_struct_set_value_n(envP, strctP, key, strlen(key), valueP);
+}
+
+
+
+void 
+xmlrpc_struct_set_value_n(xmlrpc_env *    const envP,
+                          xmlrpc_value *  const strctP,
+                          const char *    const key, 
+                          size_t          const keyLen,
+                          xmlrpc_value *  const valueP) {
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT(key != NULL);
+
+    if (xmlrpc_value_type(strctP) != XMLRPC_TYPE_STRUCT)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TYPE_ERROR,
+            "Trying to set value in something not a struct.  "
+            "Type is %d; struct is %d",
+            xmlrpc_value_type(strctP), XMLRPC_TYPE_STRUCT);
+    else {
+        xmlrpc_value * keyvalP;
+
+        /* Get the key as an xmlrpc_value */
+        keyvalP = xmlrpc_build_value(envP, "s#", key, keyLen);
+        if (!envP->fault_occurred)
+            xmlrpc_struct_set_value_v(envP, strctP, keyvalP, valueP);
+
+        xmlrpc_DECREF(keyvalP);
+    }
+}
+
+
+
+void 
+xmlrpc_struct_set_value_v(xmlrpc_env *   const envP,
+                          xmlrpc_value * const strctP,
+                          xmlrpc_value * const keyvalP,
+                          xmlrpc_value * const valueP) {
+
+    char *key;
+    size_t key_len;
+    int index;
+    _struct_member *members, *member, new_member;
+    xmlrpc_value *old_value;
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(strctP);
+    XMLRPC_ASSERT_VALUE_OK(keyvalP);
+    XMLRPC_ASSERT_VALUE_OK(valueP);
+
+    XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
+    XMLRPC_TYPE_CHECK(envP, keyvalP, XMLRPC_TYPE_STRING);
+
+    key = XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block);
+    key_len = XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block) - 1;
+    index = find_member(strctP, key, key_len);
+
+    if (index >= 0) {
+        /* Change the value of an existing member. (But be careful--the
+        ** original and new values might be the same object, so watch
+        ** the order of INCREF and DECREF calls!) */
+        members = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block);
+        member = &members[index];
+
+        /* Juggle our references. */
+        old_value = member->value;
+        member->value = valueP;
+        xmlrpc_INCREF(member->value);
+        xmlrpc_DECREF(old_value);
+    } else {
+        /* Add a new member. */
+        new_member.key_hash = get_hash(key, key_len);
+        new_member.key      = keyvalP;
+        new_member.value    = valueP;
+        XMLRPC_MEMBLOCK_APPEND(_struct_member, envP, &strctP->_block,
+                               &new_member, 1);
+        XMLRPC_FAIL_IF_FAULT(envP);
+        xmlrpc_INCREF(keyvalP);
+        xmlrpc_INCREF(valueP);
+    }
+
+cleanup:
+    return;
+}
+
+
+
+/* Note that the order of keys and values is undefined, and may change
+   when you modify the struct.
+*/
+
+void 
+xmlrpc_struct_read_member(xmlrpc_env *    const envP,
+                          xmlrpc_value *  const structP,
+                          unsigned int    const index,
+                          xmlrpc_value ** const keyvalP,
+                          xmlrpc_value ** const valueP) {
+
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(structP);
+    XMLRPC_ASSERT_PTR_OK(keyvalP);
+    XMLRPC_ASSERT_PTR_OK(valueP);
+
+    if (structP->_type != XMLRPC_TYPE_STRUCT)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_TYPE_ERROR, "Attempt to read a struct member "
+            "of something that is not a struct");
+    else {
+        _struct_member * const members =
+            XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
+        size_t const size = 
+            XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block);
+
+        if (index >= size)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INDEX_ERROR, "Index %u is beyond the end of "
+                "the %u-member structure", index, (unsigned int)size);
+        else {
+            _struct_member * const memberP = &members[index];
+            *keyvalP = memberP->key;
+            xmlrpc_INCREF(memberP->key);
+            *valueP = memberP->value;
+            xmlrpc_INCREF(memberP->value);
+        }
+    }
+}
+
+
+
+void 
+xmlrpc_struct_get_key_and_value(xmlrpc_env *    const envP,
+                                xmlrpc_value *  const structP,
+                                int             const index,
+                                xmlrpc_value ** const keyvalP,
+                                xmlrpc_value ** const valueP) {
+/*----------------------------------------------------------------------------
+   Same as xmlrpc_struct_read_member(), except doesn't take a reference
+   to the returned value.
+
+   This is obsolete.
+-----------------------------------------------------------------------------*/
+    XMLRPC_ASSERT_ENV_OK(envP);
+    XMLRPC_ASSERT_VALUE_OK(structP);
+    XMLRPC_ASSERT_PTR_OK(keyvalP);
+    XMLRPC_ASSERT_PTR_OK(valueP);
+
+    if (index < 0)
+        xmlrpc_env_set_fault_formatted(
+            envP, XMLRPC_INDEX_ERROR, "Index %d is negative.", index);
+    else {
+        xmlrpc_struct_read_member(envP, structP, index, keyvalP, valueP);
+        if (!envP->fault_occurred) {
+            xmlrpc_DECREF(*keyvalP);
+            xmlrpc_DECREF(*valueP);
+        }
+    }
+    if (envP->fault_occurred) {
+        *keyvalP = NULL;
+        *valueP = NULL;
+    }
+}
diff --git a/src/xmlrpc_utf8.c b/src/xmlrpc_utf8.c
new file mode 100644 (file)
index 0000000..daec5ce
--- /dev/null
@@ -0,0 +1,386 @@
+/* Copyright (C) 2001 by Eric Kidd. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission. 
+**  
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE. */
+
+
+/*=========================================================================
+**  XML-RPC UTF-8 Utilities
+**=========================================================================
+**  Routines for validating, encoding and decoding UTF-8 data.  We try to
+**  be very, very strict about invalid UTF-8 data.
+**
+**  All of the code in this file assumes that your machine represents
+**  wchar_t as a 16-bit (or wider) character containing UCS-2 data.  If this
+**  assumption is incorrect, you may need to replace this file.
+**
+**  For lots of information on Unicode and UTF-8 decoding, see:
+**    http://www.cl.cam.ac.uk/~mgk25/unicode.html
+*/
+
+#include "xmlrpc_config.h"
+
+#include "xmlrpc-c/base.h"
+
+#if HAVE_UNICODE_WCHAR
+
+/*=========================================================================
+**  Tables and Constants
+**=========================================================================
+**  We use a variety of tables and constants to help decode and validate
+**  UTF-8 data.
+*/
+
+/* The number of bytes in a UTF-8 sequence starting with the character used
+** as the array index.  A zero entry indicates an illegal initial byte.
+** This table was generated using a Perl script and information from the
+** UTF-8 standard.
+**
+** Fredrik Lundh's UTF-8 decoder Python 2.0 uses a similar table.  But
+** since Python 2.0 has the icky CNRI license, I regenerated this
+** table from scratch and wrote my own decoder. */
+static unsigned char utf8_seq_length[256] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0
+};
+
+/* The minimum legal character value for a UTF-8 sequence of the given
+** length.  We have to check this to avoid accepting "overlong" UTF-8
+** sequences, which use more bytes than necessary to encode a given
+** character.  Such sequences are commonly used by evil people to bypass
+** filters and security checks.  This table is based on the UTF-8-test.txt
+** file by Markus Kuhn <mkuhn@acm.org>. */
+static wchar_t utf8_min_char_for_length[4] = {
+    0,          /* Length 0: Not used (meaningless) */
+    0x0000,     /* Length 1: Not used (special-cased) */
+    0x0080,     /* Length 2 */
+    0x0800      /* Length 3 */
+
+#if 0
+    /* These are only useful on systems where wchar_t is 32-bits wide
+    ** and supports full UCS-4. */
+    0x00010000, /* Length 4 */
+    0x00200000, /* Length 5 */
+    0x04000000  /* Length 6 */
+#endif
+};
+
+/* This is the maximum legal 16-byte (UCS-2) character.  Again, this
+** information is based on UTF-8-test.txt. */
+#define UCS2_MAX_LEGAL_CHARACTER (0xFFFD)
+
+/* First and last UTF-16 surrogate characters.  These are *not* legal UCS-2
+** characters--they're used to code for UCS-4 characters when using
+** UTF-16.  They should never appear in decoded UTF-8 data!  Again, these
+** could hypothetically be used to bypass security measures on some machines.
+** Based on UTF-8-test.txt. */
+#define UTF16_FIRST_SURROGATE (0xD800)
+#define UTF16_LAST_SURROGATE  (0xDFFF)
+
+/* Is the character 'c' a UTF-8 continuation character? */
+#define IS_CONTINUATION(c) (((c) & 0xC0) == 0x80)
+
+/* Maximum number of bytes needed to encode a supported character. */
+#define MAX_ENCODED_BYTES (3)
+
+
+/*=========================================================================
+**  decode_utf8
+**=========================================================================
+**  Internal routine which decodes (or validates) a UTF-8 string.
+**  To validate, set io_buff and out_buff_len to NULL.  To decode, allocate
+**  a sufficiently large buffer, pass it as io_buff, and pass a pointer as
+**  as out_buff_len.  The data will be written to the buffer, and the
+**  length to out_buff_len.
+**
+**  We assume that wchar_t holds a single UCS-2 character in native-endian
+**  byte ordering.
+*/
+
+static void 
+decode_utf8(xmlrpc_env * const env,
+            const char * const utf8_data,
+            size_t       const utf8_len,
+            wchar_t *    const io_buff,
+            size_t *     const out_buff_len) {
+
+    size_t i, length, out_pos;
+    char init, con1, con2;
+    wchar_t wc;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_PTR_OK(utf8_data);
+    XMLRPC_ASSERT((!io_buff && !out_buff_len) ||
+                  (io_buff && out_buff_len));
+
+    /* Suppress GCC warning about possibly undefined variable. */
+    wc = 0;
+
+    i = 0;
+    out_pos = 0;
+    while (i < utf8_len) {
+        init = utf8_data[i];
+        if ((init & 0x80) == 0x00) {
+            /* Convert ASCII character to wide character. */
+            wc = init;
+            i++;
+        } else {
+            /* Look up the length of this UTF-8 sequence. */
+            length = utf8_seq_length[(unsigned char) init];
+            
+            /* Check to make sure we have enough bytes to convert. */
+            if (i + length > utf8_len)
+                XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR,
+                            "Truncated UTF-8 sequence");
+            
+            /* Decode a multibyte UTF-8 sequence. */
+            switch (length) {
+            case 0:
+                XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR,
+                            "Invalid UTF-8 initial byte");
+                
+            case 2:
+                /* 110xxxxx 10xxxxxx */
+                con1 = utf8_data[i+1];
+                if (!IS_CONTINUATION(con1))
+                    XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR,
+                                "UTF-8 sequence too short");
+                wc = ((((wchar_t) (init & 0x1F)) <<  6) |
+                      (((wchar_t) (con1 & 0x3F))));
+                break;
+                
+            case 3:
+                /* 1110xxxx 10xxxxxx 10xxxxxx */
+                con1 = utf8_data[i+1];
+                con2 = utf8_data[i+2];
+                if (!IS_CONTINUATION(con1) || !IS_CONTINUATION(con2))
+                    XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR,
+                                "UTF-8 sequence too short");
+                wc = ((((wchar_t) (init & 0x0F)) << 12) |
+                      (((wchar_t) (con1 & 0x3F)) <<  6) |
+                      (((wchar_t) (con2 & 0x3F))));
+                break;
+                
+            case 4:
+                /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+            case 5:
+                /* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+            case 6:
+                /* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+                XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR,
+                            "UCS-4 characters not supported");
+                
+            default:
+                XMLRPC_ASSERT("Error in UTF-8 decoder tables");
+            }
+            
+            /* Advance to the end of the sequence. */
+            i += length;
+            
+            /* Check for illegal UCS-2 characters. */
+            if (wc > UCS2_MAX_LEGAL_CHARACTER)
+                XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR,
+                            "UCS-2 characters > U+FFFD are illegal");
+            
+            /* Check for UTF-16 surrogates. */
+            if (UTF16_FIRST_SURROGATE <= wc && wc <= UTF16_LAST_SURROGATE)
+                XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR,
+                            "UTF-16 surrogates may not appear in UTF-8 data");
+            
+            /* Check for overlong sequences. */
+            if (wc < utf8_min_char_for_length[length])
+                XMLRPC_FAIL(env, XMLRPC_INVALID_UTF8_ERROR,
+                            "Overlong UTF-8 sequence not allowed");
+        }
+        
+        /* If we have a buffer, write our character to it. */
+        if (io_buff) {
+            io_buff[out_pos++] = wc;
+        }
+    }
+    
+    /* Record the number of characters we found. */
+    if (out_buff_len)
+        *out_buff_len = out_pos;
+    
+            cleanup:
+    if (env->fault_occurred) {
+        if (out_buff_len)
+            *out_buff_len = 0;
+    }
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_validate_utf8
+**=========================================================================
+**  Make sure that a UTF-8 string is valid.
+*/
+
+void 
+xmlrpc_validate_utf8 (xmlrpc_env * const env,
+                      const char * const utf8_data,
+                      size_t       const utf8_len) {
+
+    decode_utf8(env, utf8_data, utf8_len, NULL, NULL);
+}
+
+
+
+xmlrpc_mem_block *
+xmlrpc_utf8_to_wcs(xmlrpc_env * const envP,
+                   const char * const utf8_data,
+                   size_t       const utf8_len) {
+/*----------------------------------------------------------------------------
+  Decode UTF-8 string to a "wide character string".  This function
+  returns an xmlrpc_mem_block with an element type of wchar_t.  Don't
+  try to intepret the block in a bytewise fashion--it won't work in
+  any useful or portable fashion.
+-----------------------------------------------------------------------------*/
+    xmlrpc_mem_block *output;
+    size_t wcs_length;
+
+    /* Allocate a memory block large enough to hold any possible output.
+       We assume that each byte of the input may decode to a whcar_t.
+    */
+    output = XMLRPC_MEMBLOCK_NEW(wchar_t, envP, utf8_len);
+    if (!envP->fault_occurred) {
+        /* Decode the UTF-8 data. */
+        decode_utf8(envP, utf8_data, utf8_len,
+                    XMLRPC_MEMBLOCK_CONTENTS(wchar_t, output),
+                    &wcs_length);
+        if (!envP->fault_occurred) {
+            /* We can't have overrun our buffer. */
+            XMLRPC_ASSERT(wcs_length <= utf8_len);
+
+            /* Correct the length of the memory block. */
+            XMLRPC_MEMBLOCK_RESIZE(wchar_t, envP, output, wcs_length);
+        }
+        if (envP->fault_occurred)
+            xmlrpc_mem_block_free(output);
+    }
+    if (envP->fault_occurred)
+        output = NULL;
+
+    return output;
+}
+
+
+
+/*=========================================================================
+**  xmlrpc_utf8_to_wcs
+**=========================================================================
+**  Encode a "wide character string" as UTF-8.
+*/
+
+xmlrpc_mem_block *xmlrpc_wcs_to_utf8 (xmlrpc_env *env,
+                                      wchar_t *wcs_data,
+                                      size_t wcs_len)
+{
+    size_t estimate, bytes_used, i;
+    xmlrpc_mem_block *output;
+    unsigned char *buffer;
+    wchar_t wc;
+
+    XMLRPC_ASSERT_ENV_OK(env);
+    XMLRPC_ASSERT_PTR_OK(wcs_data);
+
+    /* Error-handling preconditions. */
+    output = NULL;
+
+    /* Allocate a memory block large enough to hold any possible output.
+    ** We assume that every wchar might encode to the maximum length. */
+    estimate = wcs_len * MAX_ENCODED_BYTES;
+    output = XMLRPC_TYPED_MEM_BLOCK_NEW(char, env, estimate);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+    /* Output our characters. */
+    buffer = (unsigned char*) XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output);
+    bytes_used = 0;
+    for (i = 0; i < wcs_len; i++) {
+        wc = wcs_data[i];
+        if (wc <= 0x007F) {
+            buffer[bytes_used++] = wc & 0x7F;
+        } else if (wc <= 0x07FF) {
+            /* 110xxxxx 10xxxxxx */
+            buffer[bytes_used++] = 0xC0 | (wc >> 6);
+            buffer[bytes_used++] = 0x80 | (wc & 0x3F);
+        } else if (wc <= 0xFFFF) {
+            /* 1110xxxx 10xxxxxx 10xxxxxx */
+            buffer[bytes_used++] = 0xE0 | (wc >> 12);
+            buffer[bytes_used++] = 0x80 | ((wc >> 6) & 0x3F);
+            buffer[bytes_used++] = 0x80 | (wc & 0x3F);
+        } else {
+            XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR,
+                        "Don't know how to encode UCS-4 characters yet");
+        }
+    }
+
+    /* Make sure we didn't overrun our buffer. */
+    XMLRPC_ASSERT(bytes_used <= estimate);
+
+    /* Correct the length of the memory block. */
+    XMLRPC_TYPED_MEM_BLOCK_RESIZE(char, env, output, bytes_used);
+    XMLRPC_FAIL_IF_FAULT(env);
+
+ cleanup:
+    if (env->fault_occurred) {
+        if (output)
+            xmlrpc_mem_block_free(output);
+        return NULL;
+    }
+    return output;
+}
+
+
+
+#else /* HAVE_UNICODE_WCHAR */
+
+xmlrpc_mem_block *
+xmlrpc_utf8_to_wcs(xmlrpc_env * const envP,
+                   const char * const utf8_data ATTR_UNUSED,
+                   size_t       const utf8_len ATTR_UNUSED) {
+
+    xmlrpc_faultf(envP, "INTERNAL ERROR: xmlrpc_utf8_to_wcs() called "
+                  "on a system that doesn't do Unicode!");
+
+    return NULL;
+}
+#endif /* HAVE_UNICODE_WCHAR */
+
+
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/tools/.cvsignore b/tools/.cvsignore
new file mode 100644 (file)
index 0000000..f3c7a7c
--- /dev/null
@@ -0,0 +1 @@
+Makefile
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644 (file)
index 0000000..8f4ee60
--- /dev/null
@@ -0,0 +1,33 @@
+SUBDIR=tools
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/..
+BUILDDIR = $(SRCDIR)
+endif
+
+include $(SRCDIR)/Makefile.config
+
+SUBDIRS = binmode-rpc-kit turbocharger
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  SUBDIRS += xmlrpc xmlrpc_transport
+endif
+
+ifeq ($(ENABLE_CPLUSPLUS),yes)
+  SUBDIRS += xml-rpc-api2cpp
+endif
+
+.PHONY: all clean distclean install check dep
+
+all: $(SUBDIRS:%=%/all)
+
+clean: $(SUBDIRS:%=%/clean)
+
+distclean: $(SUBDIRS:%=%/distclean)
+
+install: $(SUBDIRS:%=%/install)
+
+check:
+
+dep: $(SUBDIRS:%=%/dep)
+
+include $(SRCDIR)/Makefile.common
diff --git a/tools/Makefile.common b/tools/Makefile.common
new file mode 100644 (file)
index 0000000..2bac178
--- /dev/null
@@ -0,0 +1,36 @@
+# -*-makefile-*-    <-- an Emacs control
+
+CLIENT_LDLIBS = -L$(BUILDDIR)/src/.libs -lxmlrpc_client -lxmlrpc
+
+ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
+  CLIENT_LDLIBS += $(shell libwww-config --libs)
+endif
+ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
+  CLIENT_LDLIBS += $(shell curl-config --libs)
+endif
+ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
+  CLIENT_LDLIBS += $(shell wininet-config --libs)
+endif
+
+CLIENT_LDLIBS += $(LDLIBS_XML)
+
+CLIENT_LDLIBS += -L$(BUILDDIR)/lib/libutil/.libs -lxmlrpc_util
+
+
+UTIL_DIR = $(BUILDDIR)/lib/util
+
+BUILDABLE_UTILS = cmdline_parser.o getoptx.o
+
+$(BUILDABLE_UTILS:%=$(UTIL_DIR)/%): FORCE
+       $(MAKE) -C $(dir $@) $(notdir $@)
+
+include $(SRCDIR)/Makefile.common
+
+.PHONY: install
+install: install-common
+
+.PHONY: check
+check:
+
+.PHONY: FORCE
+FORCE:
diff --git a/tools/binmode-rpc-kit/COPYING b/tools/binmode-rpc-kit/COPYING
new file mode 100644 (file)
index 0000000..9a97cb3
--- /dev/null
@@ -0,0 +1,24 @@
+Copyright (C) 2001 by Eric Kidd. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission. 
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/tools/binmode-rpc-kit/Makefile b/tools/binmode-rpc-kit/Makefile
new file mode 100644 (file)
index 0000000..e5df68d
--- /dev/null
@@ -0,0 +1,5 @@
+all:
+clean:
+distclean:
+install:
+dep:
diff --git a/tools/binmode-rpc-kit/README b/tools/binmode-rpc-kit/README
new file mode 100644 (file)
index 0000000..029b5b1
--- /dev/null
@@ -0,0 +1,31 @@
+Binmode RPC Implementor's Kit
+=============================
+
+Version: 0.1
+Author:  Eric Kidd <eric.kidd@pobox.com>
+Date:    31 January 2001
+
+The Binmode RPC Implementor's Kit was created as part the xmlrpc-c project.
+
+  http://xmlrpc-c.sourceforge.net/
+
+The following files are included:
+
+  README                This file
+  COPYING               A standard disclaimer, etc.
+  binmode-rpc-rfc.txt   The current draft of the standard
+  oct2bin               A Perl script for turning the notation used by
+                        the standard into actual binary data.
+  binmode-rpc2xml-rpc   A script which translates a Binmode RPC packet
+                        back into XML. You can use this for dumping wire
+                        messages. (It also catches the most obvious ways
+                        to misimplement the standard, so try it on your
+                        output data.)
+  examples/             Examples and counter-examples from the standard in
+                        machine-readable format.
+
+If you have any questions, please ask on the xmlrpc-c-devel mailing list:
+
+  http://xmlrpc-c.sourceforge.net/lists.php
+
+Thank you for investigating Binmode RPC. Share and enjoy!
diff --git a/tools/binmode-rpc-kit/binmode-rpc-rfc.txt b/tools/binmode-rpc-kit/binmode-rpc-rfc.txt
new file mode 100644 (file)
index 0000000..b59208a
--- /dev/null
@@ -0,0 +1,338 @@
+This is a draft, and subject to change. Please do not implement it
+yet. Thank you!
+
+Examples can be found at the bottom of the file.
+
+Thank you for your feedback!
+
+Eric Kidd
+eric.kidd@pobox.com
+30 January 2001
+
+
+The Binmode RPC Protocol
+========================
+
+Binmode RPC is an ultra-lightweight RPC protocol designed for 100%
+compatibility with XML-RPC <http://www.xmlrpc.com/>. It emphasizes
+simplicity, dynamically-typed data, and extreme ease of implementation.
+
+Two XML-RPC implementations that support 'binmode-rpc' may negotiate away
+the XML part of XML-RPC, and replace it with a simple binary protocol.
+
+Design goals:
+
+  * The complete specification should fit in a 350-line text file. :-)
+  * The protocol should be easy to implement.
+  * The protocol should provide a high degree of compression.
+  * The protocol should be very fast--faster than zlib compression.
+  * The protocol must be implementable in portable ANSI C, with no
+    './configure' checks.
+  * The protocol must not contain any options, variant encodings
+    or similar hair. If you want DCE/RPC, you know where to find it.
+  * All protocol operations must be performed at the byte level
+    (except for UTF-8 encoding and decoding).
+  * The protocol must be semi-readable in a hex dump or Emacs buffer.
+  * The protocol must efficiently encode boxcarred calls that are
+    implemented using 'system.multicall'.
+  * The protocol must support an efficient encoding for
+    frequently-repeated string values.
+
+  * The protocol must never be sent to clients or servers which
+    don't support it.
+  * There must be a way for clients and servers to active the protocol
+    if both ends of the connection support it.
+
+
+The X-XML-RPC-Extensions Header
+-------------------------------
+
+(First, we'll need a mechanism for unobtrusively announcing the presence of
+non-standard capabilities.)
+
+An XML-RPC implementation MAY advertise additional, non-standard
+capabilities using the 'X-XML-RPC-Extensions' header.
+
+Rationale: The 'X-XML-RPC-Extensions' header should be available to CGI
+scripts in the environment variable HTTP_X_XML_RPC_EXTENSIONS.
+
+If present, this header MUST contain a comma-separated list of
+keywords. Parameter information MAY be included, if desired, in the
+standard fashion used by HTTP 1.1 'Accept-Encoding' headers.
+
+  X-XML-RPC-Extensions: binmode-rpc
+  X-XML-RPC-Extensions: binmode-rpc, x-telepathic-transport
+  X-XML-RPC-Extensions: binmode-rpc,x-telepathic-transport
+  X-XML-RPC-Extensions: binmode-rpc, x-telepathic-transport;speed=low
+
+If a client sends the X-XML-RPC-Extensions header in a request, the server
+MAY use any of the specified extensions in its response.
+
+Rationale: No client may be sent non-standard data without first having
+advertised the ability to accept it.
+
+If the server includes the X-XML-RPC-Extensions header in a response, the
+client MAY use any of the specified extensions in further requests to that
+URL. The client MUST NOT assume that the same extensions are available for
+any other URL on the same server.
+
+Rationale: No server may be sent non-standard data without first having
+advertised the ability to accept it. Furthermore, this permission is
+URL-specific, since different XML-RPC implementations may be located at
+different URLs on a single server.
+
+The client SHOULD NOT cache extension information about a particular server
+for an excessive length of time (typically beyond a single program
+invocation). If the client does cache this information indefinitely, it
+SHOULD be able to cope if an extension is disabled.
+
+Rationale: The XML-RPC implementation used on the server may be changed by
+the administrator.
+
+
+The 'binmode-rpc' Extension
+-----------------------
+
+A client or server which sends the 'binmode-rpc' extension MUST accept
+message bodies of type 'application/x-binmode-rpc' in addition to the
+regular 'text/xml'.
+
+All servers which accept the binmode-rpc extension MUST also support
+standard XML-RPC, as described by <http://www.xmlrpc.org/spec>.
+
+
+The 'application/x-binmode-rpc' Format
+--------------------------------------
+
+All documents of the type 'application/x-binmode-rpc' MUST begin with the
+following byte sequence (represented here as a C string):
+
+  'binmode-rpc:'
+
+This MUST be followed by a Call or a Response, encoded as described below:
+
+  Call := 'C' String Array
+
+A Call consists of a single octet with the ASCII value 'C', followed by a
+String containing the method name and an Array containing the parameters.
+
+  Response := 'R' (Value|Fault)
+
+A Response MUST contain either a Value or a Fault.
+
+  Fault := 'F' Struct
+
+A Fault contains a regular Struct (with members as specified by the the
+XML-RPC specification).
+
+Trailing data at the end of an 'application/x-binmode-rpc' document MUST be
+ignored.
+
+
+Byte-Order of Integers
+----------------------
+
+(The following integer types don't correspond directly to XML-RPC
+integers--instead, they'll be used to *build* more complicated types.)
+
+  SignedLSB := a four-octet, signed, twos'-complement integer,
+               least-significant byte (LSB) first
+  UnsignedLSB := a four-octet, unsigned integer, LSB first
+
+Raw integer data is encoded in little-endian format.
+
+Rationale: A fixed, mandatory byte ordering is easier to implement than
+approaches which allow multiple byte orderings, and little-endian CPUs
+outnumber big-endian CPUs at the time of writing.
+
+
+Values
+------
+
+  Value := (Integer|Boolean|Double|DateTimeISO8601Binary|Array|Struct|
+            String|Other)
+
+  Integer := 'I' SignedLSB
+  Boolean := ('t'|'f')
+
+  Double := 'D' SizeOctet AsciiChar...
+  DateTimeISO8601 := '8' SizeOctet AsciiChar...
+
+These two types are encoded with an unsigned size octet followed by the
+specified number of ASCII characters. The values are encoded in the fashion
+described by the XML-RPC specification.
+
+Rationale: In both these cases, we're punting. Binary floating point
+formats are highly non-portable, and cannot be easily manipulated by most
+programming languages. XML-RPC <dateTime.iso8601> values lack timezone
+information, and are therefore difficult to convert to a binary format.
+
+  Binary := 'B' UnsignedLSB Octet...
+
+This corresponds to the XML-RPC <base64> type, but without any encoding.
+The UnsignedLSB specifies the number of octets of data.
+
+  Array := 'A' UnsignedLSB Value...
+
+The UnsignedLSB specifies the number of values in the array.
+
+  Struct := 'S' UnsignedLSB (String,Value)...
+
+The UnsignedLSB specifies the number of String,Value pairs in the struct.
+The strings are keys; the values may be of any type.
+
+  Other := 'O' String Binary
+
+Future XML-RPC types (if any) may be sent a String containing the type name
+and a Binary block (as above) containing type-specific data.
+Implementations MUST NOT encode any of the standard types using this
+construct. Implementations MAY signal an error if data of type Other is
+encountered.
+
+Rationale: This is allowed to cause an error because most applications
+won't understand the contents anyway. But if new types are added, dumb
+gateways will be able to manipulate them in encapsulated format (if they so
+desire).
+
+
+Strings
+-------
+
+  String := (RegularString|RecordedString|RecalledString)
+
+We have three types of strings.
+
+  RegularString := 'U' StringData
+  StringData := UnsignedLSB Utf8Octet...
+
+Strings are encoded in UTF-8 format. The UnsignedLSB specifies the number
+of UTF-8 octets. Implementations SHOULD raise an error if they encounter
+invalid UTF-8 data (e.g., ISO Latin 1 characters).
+
+Rationale: Technically speaking, XML-RPC is limited to plain ASCII
+characters, and may not contain 8-bit or 16-bit characters in any coding
+system. But since XML-RPC is based on XML, adding Unicode is a trivial
+enhancement to the basic protocol, and *somebody* will make it sooner or
+later. When that day arrives, we want to be able to encode Unicode
+characters.
+
+Implements MUST encode UTF-8 characters using the minimum number of octets.
+Implementations SHOULD raise an error if they encounter any UTF-8
+characters encoded using more than the minimum number of octets.
+
+Rationale: Overlong UTF-8 encodings are sometimes used to bypass string
+validation in security code. They serve no legitimate purpose, either. So
+to improve the overall security of the Universe, we work hard to discourage
+them.
+
+UTF-8 & Unicode FAQ: http://www.cl.cam.ac.uk/~mgk25/unicode.html
+
+  RecordedString := '>' CodebookPosition StringData
+  RecalledString := '<' CodebookPosition
+  CodebookPosition := UnsignedOctet
+
+The 'binmode' format supports a 256-entry "codebook" of strings. At the
+start of a data stream, the codebook is empty. When the decoder
+encounters a RecordedString, it MUST store it into the specified codebook
+position (and then proceed to decode it as a regular string).
+
+When the decoder encounters a RecalledString, it MUST look it up in the
+specified codebook position. If that codebook position has been set, the
+implementation MUST use the string value found in the codebook. If the
+position has not been set, the implementation MUST stop decoding and raise
+an error. It is legal to change a codebook position once it has been set;
+the most recent value applies.
+
+A RecordedString or a RecalledString may be used anywhere a RegularString
+may be used.
+
+Rationale: XML-RPC data tends to contain large numbers of identical
+strings. (These are typically the names of <struct> members or the names of
+methods in a multicall.) To get any kind of reasonable data compression,
+it's necessary to have some way of compressing these values. The codebook
+mechanism is relatively simple and uncomplicated.
+
+Implementations MAY choose not to use this feature when encoding data, but
+MUST understand it when decoding data.
+
+Rationale: On the decoding end of things, this feature is trivial to
+implement, and must be present for the sake of interoperability. On the
+encoding end of things, however, making effective use of this feature is
+slightly trickier, so implementations are allowed (but not encouraged) to
+omit it.
+
+
+Compliance
+----------
+
+Implementations MUST implement all features of this protocol correctly,
+particularly on the decoding end. In the case of this protocol, a 95% correct
+implementation is 100% broken. Yes, this statement is redundant. ;-)
+
+
+Examples
+--------
+
+Non-ASCII octets are specified as in C strings. Continued lines are
+indicated by a trailing '\'; these should be joined together as one
+sequence of bytes.
+
+binmode-rpc:CU\003\0\0\0addA\002\0\0\0I\002\0\0\0I\002\0\0\0
+
+binmode-rpc:RI\004\0\0\0
+
+binmode-rpc:RFS\002\0\0\0 \
+U\011\0\0\0faultCodeI\001\0\0\0 \
+U\013\0\0\0faultStringU\021\0\0\0An error occurred
+
+binmode-rpc:RA\006\0\0\0 \
+>\000\003\0\0\0foo \
+>\001\003\0\0\0bar \
+<\000 \
+>\000\003\0\0\0baz \
+<\000 \
+<\001
+
+(This deserializes to ['foo', 'bar', 'foo', 'baz', 'baz', 'bar'].)
+
+binmode-rpc:RU\042\0\0\0Copyright \302\251 1995 J. Random Hacker
+
+(This is based on an example in the Unicode/UTF-8 FAQ (see above).)
+
+binmode-rpc:RA\010\0\0\0 \
+I\006\0\0\0 \
+tf \
+D\0042.75 \
+8\02119980717T14:08:55 \
+U\003\0\0\0foo \
+B\003\0\0\0abc \
+S\002\0\0\0U\003\0\0\0runt
+
+Counter-Examples
+----------------
+
+The following specimens are illegal, and SHOULD be rejected by a compliant
+implementation. Please test your code.
+
+* A different format name:
+
+  binmode-rpc2:RI\004\0\0\0
+
+* A built-in type incorrectly encoded using 'O':
+
+  binmode-rpc:ROU\006\0\0\0stringB\003\0\0\0xyz
+
+* A recall of an unrecorded string:
+
+  binmode-rpc:R<\002
+
+* ISO Latin 1 data in a string. (UTF-8 required!)
+
+  binmode-rpc:RU\041\0\0\0Copyright \251 1995 J. Random Hacker
+  
+* UTF-8 character encoded with too many octets (based on an example in the
+  Unicode/UTF-8 FAQ):
+
+  binmode-rpc:RU\041\0\0\0Bad linefeed: \300\212 (too many bytes)
+
+A compliant implementation MUST NOT send any of these sequences.
diff --git a/tools/binmode-rpc-kit/binmode-rpc2xml-rpc b/tools/binmode-rpc-kit/binmode-rpc2xml-rpc
new file mode 100755 (executable)
index 0000000..2625629
--- /dev/null
@@ -0,0 +1,552 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+# Some constants.
+my $crlf = "\015\012";
+
+# Try to load our external libraries, but fail gracefully.
+eval {
+    require Frontier::Client;
+    require MIME::Base64;
+};
+if ($@) {
+    print STDERR <<"EOD";
+This script requires Ken MacLeod\'s Frontier::RPC2 module. You can get this
+from CPAN or from his website at http://bitsko.slc.ut.us/~ken/xml-rpc/ .
+
+For installation instructions, see the XML-RPC HOWTO at:
+    http://www.linuxdoc.org/HOWTO/XML-RPC-HOWTO/index.html
+
+This script also requires MIME::Base64. You can get this from CPAN.
+EOD
+    exit 1;
+}
+
+# Parse our command-line arguments.
+if (@ARGV != 0) {
+    print STDERR "Usage: binmode-rpc2xml-rpc < data.binmode > data.xml\n";
+    exit 1;
+}
+
+# Perform our I/O in binary mode (hence the name of the protocol).
+binmode STDIN;  # Because we're reading raw binary data.
+binmode STDOUT; # Because we want our XML left unmolested.
+
+# Just suck all our input into one string and glom it together.
+my $binmode_data = join('', <STDIN>);
+
+# Check for the mandatory header.
+unless ($binmode_data =~ /^binmode-rpc:/) {
+    die "$0: No 'binmode-rpc:' header present, stopping";
+}
+
+# Set our decoding-position counter to point just past the header, and
+# our end pointer to just beyond the end of the entire message.
+my $position = length('binmode-rpc:');
+my $end = length($binmode_data);
+
+# Set our starting output indentation to zero (for the pretty-printer).
+my $indentation = 0;
+
+# Build an empty codebook of strings.
+my @codebook;
+
+# Begin the hard work.
+decode_call_or_response();
+
+# Print a warning if there's leftover data.
+if ($position != $end) {
+    printf STDERR "binmode-rpc2xml-rpc: warning: Trailing data ignored\n";
+}
+
+# We're done!
+exit (0);
+
+
+#--------------------------------------------------------------------------
+#  Pretty-printing
+#--------------------------------------------------------------------------
+
+sub escape_string ($) {
+    my ($string) = @_;
+    $string =~ s/&/&amp;/g;
+    $string =~ s/</&lt;/g;
+    $string =~ s/\"/&quot;/g;
+    return $string;
+}
+
+sub push_indentation_level () {
+    $indentation += 2;
+}
+
+sub pop_indentation_level () {
+    $indentation -= 2;
+}
+
+sub print_xml_line ($) {
+    my ($xml) = @_;
+    print STDOUT (' ' x $indentation) . $xml . $crlf;
+}
+
+
+#--------------------------------------------------------------------------
+#  Raw input routines
+#--------------------------------------------------------------------------
+#  These routines read raw input from our string, advance the current
+#  position, and return something in a Perl-friendly format.
+#
+#  This is all icky binary I/O using Perl's built-in unpack function.
+
+sub read_byte () {
+    die "Unexpected end of input" unless ($position + 1 <= $end);
+    my $byte = unpack('C', substr($binmode_data, $position, 1));
+    $position += 1;
+    die "Weird error decoding byte" unless (defined $byte);
+    return $byte;
+}
+
+sub peek_character () {
+    die "Unexpected end of input" unless ($position + 1 <= $end);
+    my $byte = chr(unpack('c', substr($binmode_data, $position, 1)));
+    die "Weird error decoding character" unless (defined $byte);
+    return $byte;
+}
+
+sub read_character () {
+    my $byte = peek_character();
+    $position += 1;
+    return $byte;
+}
+
+sub read_unsigned_lsb () {
+    die "Unexpected end of input" unless ($position + 4 <= $end);
+    my $integer = unpack('V', substr($binmode_data, $position, 4));
+    $position += 4;
+    die "Weird error decoding integer" unless (defined $integer);
+    unless ($integer >= 0) {
+       die "Perl can't handle 32-bit unsigned integers portably, stopping";
+    }
+    return $integer;
+}
+
+sub read_signed_lsb () {
+    die "Unexpected end of input" unless ($position + 4 <= $end);
+    my $integer = unpack('V', substr($binmode_data, $position, 4));
+    $position += 4;
+    die "Weird error decoding integer" unless (defined $integer);
+    return $integer;
+}
+
+sub read_data ($) {
+    my ($length) = @_;
+    die "Unexpected end of input" unless ($position + $length <= $end);
+    my $data = unpack("a$length", substr($binmode_data, $position, $length));
+    $position += $length;
+    die "Weird error decoding data" unless (defined $data);
+    die "Wrong data length" unless (length($data) == $length);
+    return $data;
+}
+
+sub read_data_w_byte_length () {
+    my $length = read_byte();
+    return read_data($length);
+}
+
+sub read_data_w_unsigned_lsb_length () {
+    my $length = read_unsigned_lsb();
+    return read_data($length)
+}
+
+sub read_string_data () {
+    my $string = read_data_w_unsigned_lsb_length();
+    validate_utf8($string);
+    return $string;
+}
+
+
+#--------------------------------------------------------------------------
+#  High-level input routines
+#--------------------------------------------------------------------------
+#  These use the low-level input routines to read data from the buffer,
+#  and then convert it into Frontier::RPC2 objects.
+
+sub read_value () {
+    my $type = read_character();
+    #print STDERR "DEBUG: Reading from '$type'\n";
+    if ($type eq 'I') {
+       return _read_int_value();
+    } elsif ($type eq 't') {
+       return Frontier::RPC2::Boolean->new(1);
+    } elsif ($type eq 'f') {
+       return Frontier::RPC2::Boolean->new(0);
+    } elsif ($type eq 'D') {
+       return _read_double_value();
+    } elsif ($type eq '8') {
+       return _read_dateTime_value();
+    } elsif ($type eq 'B') {
+       return _read_base64_value();
+    } elsif ($type eq 'A') {
+       return _read_array_value();
+    } elsif ($type eq 'S') {
+       return _read_struct_value();
+    } elsif ($type eq 'U') {
+       return _read_regular_string_value();
+    } elsif ($type eq '>') {
+       return _read_recorded_string_value();
+    } elsif ($type eq '<') {
+       return _read_recalled_string_value();
+    } elsif ($type eq 'O') {
+       die "Type 'O' Binmode RPC data not supported";
+    } else {
+       die "Type '$type' Binmode RPC data does not exist";
+    }
+}
+
+sub read_value_and_typecheck ($) {
+    my ($wanted_type) = @_;
+    my $value = read_value();
+    my $value_type = ref($value);
+    die "$0: Expected $wanted_type, got $value_type, stopping"
+       unless ($wanted_type eq $value_type);
+    return $value;
+}
+
+sub _read_int_value () {
+    return Frontier::RPC2::Integer->new(read_signed_lsb);
+}
+
+sub _read_double_value () {
+    return Frontier::RPC2::Double->new(read_data_w_byte_length);
+}
+
+sub _read_dateTime_value () {
+    return Frontier::RPC2::DateTime::ISO8601->new(read_data_w_byte_length);
+}
+
+sub _read_base64_value () {
+    my $binary = read_data_w_unsigned_lsb_length;
+    my $encoded = MIME::Base64::encode_base64($binary, $crlf);
+    return Frontier::RPC2::Base64->new($encoded);
+}
+
+sub _read_array_value () {
+    my $size = read_unsigned_lsb;
+    my @values;
+    for (my $i = 0; $i < $size; $i++) {
+       push @values, read_value;
+    }
+    return \@values;
+}
+
+sub _read_struct_value () {
+    my $size = read_unsigned_lsb;
+    my %struct;
+    for (my $i = 0; $i < $size; $i++) {
+       my $key = read_value_and_typecheck('Frontier::RPC2::String');
+       $struct{$key->value} = read_value;
+    }
+    return \%struct;
+}
+
+sub _read_regular_string_value () {
+    return Frontier::RPC2::String->new(read_string_data);
+}
+
+sub _read_recorded_string_value () {
+    my $codebook_entry = read_byte;
+    my $string = Frontier::RPC2::String->new(read_string_data);
+    $codebook[$codebook_entry] = $string;
+    return $string;
+}
+
+sub _read_recalled_string_value () {
+    my $codebook_entry = read_byte;
+    my $string = $codebook[$codebook_entry];
+    unless (defined $string) {
+       die "$0: Attempted to use undefined codebook position $codebook_entry";
+    }
+    return $string;
+}
+
+
+#--------------------------------------------------------------------------
+#  High-level output routines
+#--------------------------------------------------------------------------
+#  We don't use Frontier::RPC2's output routines, because we're looking
+#  for maximum readability. This is a debugging tool, after all.
+
+sub print_xml_header () {
+    print_xml_line '<?xml version="1.0" encoding="UTF-8"?>';
+}
+
+sub get_escaped_string ($) {
+    my ($value) = @_;
+    return escape_string($value->value);
+}
+
+sub print_simple_value ($$) {
+    my ($tag, $value) = @_;
+    my $string = get_escaped_string($value);
+    print_xml_line "<value><$tag>$string</$tag></value>";
+}
+
+sub print_value ($) {
+    my ($value) = @_;
+    my $type = ref($value);
+    if ($type eq 'Frontier::RPC2::Integer') {
+       print_simple_value("int", $value);
+    } elsif ($type eq 'Frontier::RPC2::Double') {
+       print_simple_value("double", $value);
+    } elsif ($type eq 'Frontier::RPC2::Boolean') {
+       print_simple_value("boolean", $value);
+    } elsif ($type eq 'Frontier::RPC2::String') {
+       print_simple_value("string", $value);
+    } elsif ($type eq 'Frontier::RPC2::DateTime::ISO8601') {
+       print_simple_value("dateTime.iso8601", $value);
+    } elsif ($type eq 'Frontier::RPC2::Base64') {
+       print_base64_data($value);
+    } elsif ($type eq 'ARRAY') {
+       print_array_value($value);
+    } elsif ($type eq 'HASH') {
+       print_struct_value($value);
+    } else {
+       die "Unxpected type '$type', stopping";
+    }
+}
+
+sub print_params ($) {
+    my ($params) = @_;
+
+    die "Wanted array" unless (ref($params) eq 'ARRAY');
+
+    print_xml_line '<params>';
+    push_indentation_level;
+
+    foreach my $item (@$params) {
+       print_xml_line '<param>';
+       push_indentation_level;
+       print_value($item);
+       pop_indentation_level;
+       print_xml_line '</param>';
+    }
+
+    pop_indentation_level;
+    print_xml_line '</params>';
+}
+
+sub print_base64_data ($) {
+    my ($value) = @_;
+    print_xml_line '<value>';
+    push_indentation_level;
+    print_xml_line '<base64>';
+    print $value->value;
+    print_xml_line '</base64>';
+    pop_indentation_level;
+    print_xml_line '</value>';    
+}
+
+sub print_array_value ($) {
+    my ($array) = @_;
+
+    print_xml_line '<value>';
+    push_indentation_level;
+    print_xml_line '<array>';
+    push_indentation_level;
+    print_xml_line '<data>';
+    push_indentation_level;
+
+    foreach my $item (@$array) {
+       print_value($item);
+    }
+
+    pop_indentation_level;
+    print_xml_line '</data>';
+    pop_indentation_level;
+    print_xml_line '</array>';
+    pop_indentation_level;
+    print_xml_line '</value>';
+}
+
+sub print_struct_value ($) {
+    my ($struct) = @_;
+
+    print_xml_line '<value>';
+    push_indentation_level;
+    print_xml_line '<struct>';
+    push_indentation_level;
+
+    for my $key (keys %$struct) {
+       print_xml_line '<member>';
+       push_indentation_level;
+       
+       my $name = escape_string($key);
+       print_xml_line "<name>$name</name>";
+       print_value($struct->{$key});
+
+       pop_indentation_level;
+       print_xml_line '</member>';
+    } 
+
+    pop_indentation_level;
+    print_xml_line '</struct>';
+    pop_indentation_level;
+    print_xml_line '</value>';
+}
+
+
+#--------------------------------------------------------------------------
+#  High-level decoder routines
+#--------------------------------------------------------------------------
+#  These routines convert Binmode RPC data into the corresponding XML-RPC
+#  documents.
+
+sub decode_call_or_response () {
+    my $type = read_character();
+    if ($type eq 'C') {
+       decode_call();
+    } elsif ($type eq 'R') {
+       decode_response();
+    } else {
+       die "$0: Unknown binmode-rpc request type '$type', stopping";
+    }
+}
+
+sub decode_call () {
+    my $namevalue = read_value_and_typecheck('Frontier::RPC2::String');
+    my $params = read_value_and_typecheck('ARRAY');
+    
+    print_xml_header;
+    print_xml_line '<methodCall>';
+    push_indentation_level;
+
+    my $name = get_escaped_string($namevalue);
+    print_xml_line "<methodName>$name</methodName>";
+
+    print_params($params);
+
+    pop_indentation_level;
+    print_xml_line '</methodCall>';
+}
+
+sub decode_response () {
+    my $maybe_fault = peek_character;
+    if ($maybe_fault eq 'F') {
+       read_character;
+       my $fault = read_value_and_typecheck('HASH');
+       print_xml_header;
+
+       print_xml_line '<methodResponse>';
+       push_indentation_level;
+       print_xml_line '<fault>';
+       push_indentation_level;
+
+       print_value $fault;
+
+       pop_indentation_level;
+       print_xml_line '</fault>';
+       pop_indentation_level;
+       print_xml_line '</methodResponse>';
+    } else {
+       my $value = read_value;
+       print_xml_header;
+       print_xml_line '<methodResponse>';
+       push_indentation_level;
+       print_params [$value];
+       pop_indentation_level;
+       print_xml_line '</methodResponse>';
+    }
+}
+
+
+#--------------------------------------------------------------------------
+#  UTF-8 Validation
+#--------------------------------------------------------------------------
+#  This is based on the UTF-8 section of the Secure Programs HOWTO.
+#    http://new.linuxnow.com/docs/content/HOWTO/Secure-Programs-HOWTO/
+#  This code *hasn't* been stress-tested for correctness yet; please see:
+#    http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+#  This is not yet good enough to be used as part of a UTF-8 decoder or
+#  security validator, but it's OK to make sure nobody is sending Latin-1.
+
+BEGIN {
+
+    use vars qw{@illegal_initial_bytes @sequence_length_info};
+
+    # Bytes are represented as data/mask pairs.
+    @illegal_initial_bytes =
+       (# 10xxxxxx                 illegal as initial byte of char (80..BF)
+        [0x80, 0xC0],   
+        # 1100000x                 illegal, overlong (C0..C1 80..BF)
+        [0xC0, 0xFE],   
+        # 11100000 100xxxxx        illegal, overlong (E0 80..9F)
+        [0xE0, 0xFF, 0x80, 0xE0],
+        # 11110000 1000xxxx        illegal, overlong (F0 80..8F)
+        [0xF0, 0xFF, 0x80, 0xF0],
+        # 11111000 10000xxx        illegal, overlong (F8 80..87)
+        [0xF8, 0xFF, 0x80, 0xF8],
+        # 11111100 100000xx        illegal, overlong (FC 80..83)
+        [0xFC, 0xFF, 0x80, 0xFC],
+        # 1111111x                 illegal; prohibited by spec
+        [0xFE, 0xFE]);
+    
+    # Items are byte, mask, sequence length.
+    @sequence_length_info =
+       (# 110xxxxx 10xxxxxx
+        [0xC0, 0xE0, 2],
+        # 1110xxxx 10xxxxxx 10xxxxxx
+        [0xE0, 0xF0, 3],
+        # 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+        [0xF0, 0xF8, 4],
+        # 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+        [0xF8, 0xFC, 5],
+        # 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+        [0xFC, 0xFE, 6]);
+}
+
+sub validate_utf8 ($) {
+    my ($string) = @_;
+    my $end = length($string);
+
+    my $i = 0;
+    while ($i < $end) {
+       my $byte = ord(substr($string, $i, 1));
+       #print STDERR "Checking byte $byte\n";
+
+       # Check for illegal bytes at the start of this sequence.
+      NEXT_CANDIDATE:
+       foreach my $illegal_byte_info (@illegal_initial_bytes) {
+           my $offset = 0;
+           for (my $j = 0; $j < @$illegal_byte_info; $j += 2) {
+               my $pattern = $illegal_byte_info->[$j];
+               my $mask = $illegal_byte_info->[$j+1];
+               my $data = ord(substr($string, $i+$offset, 1));
+               #print STDERR "  B: $byte P: $pattern M: $mask D: $data\n";
+               next NEXT_CANDIDATE unless ($data & $mask) == $pattern;
+               $offset++;
+           }
+           die "Illegal UTF-8 sequence (" . substr($string, $i, 2) . ")";
+       }
+
+       # Find the length of the sequence, and make sure we have enough data.
+       my $length = 1;
+       foreach my $length_info (@sequence_length_info) {
+           my ($pattern, $mask, $length_candidate) = @$length_info;
+           if (($byte & $mask) == $pattern) {
+               $length = $length_candidate;
+               last;
+           }
+       }
+       die "$0: Unexpected end of UTF-8 sequence, stopping"
+           unless $i + $length <= $end;
+       
+       # Verify the sequence is well-formed.
+       $i++, $length--;
+       while ($length > 0) {
+           die "$0: Malformed UTF-8 sequence, stopping"
+               unless (ord(substr($string, $i, 1)) & 0xC0) == 0x80;
+           $i++, $length--;
+       }
+    }
+    #printf STDERR "DEBUG: Verified $i bytes\n";
+}
diff --git a/tools/binmode-rpc-kit/examples/good-1.binmode b/tools/binmode-rpc-kit/examples/good-1.binmode
new file mode 100644 (file)
index 0000000..53c5740
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/good-1.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/good-1.xml b/tools/binmode-rpc-kit/examples/good-1.xml
new file mode 100644 (file)
index 0000000..3f9feaa
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<methodResponse>\r
+  <params>\r
+    <param>\r
+      <value>\r
+        <array>\r
+          <data>\r
+            <value><int>6</int></value>\r
+            <value><boolean>1</boolean></value>\r
+            <value><boolean>0</boolean></value>\r
+            <value><double>2.75</double></value>\r
+            <value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601></value>\r
+            <value><string>foo</string></value>\r
+            <value>\r
+              <base64>\r
+YWJj\r
+              </base64>\r
+            </value>\r
+            <value>\r
+              <struct>\r
+                <member>\r
+                  <name>run</name>\r
+                  <value><boolean>1</boolean></value>\r
+                </member>\r
+              </struct>\r
+            </value>\r
+          </data>\r
+        </array>\r
+      </value>\r
+    </param>\r
+  </params>\r
+</methodResponse>\r
diff --git a/tools/binmode-rpc-kit/examples/good-2.binmode b/tools/binmode-rpc-kit/examples/good-2.binmode
new file mode 100644 (file)
index 0000000..8fd69ef
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/good-2.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/good-2.xml b/tools/binmode-rpc-kit/examples/good-2.xml
new file mode 100644 (file)
index 0000000..ab1db1a
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<methodCall>\r
+  <methodName>add</methodName>\r
+  <params>\r
+    <param>\r
+      <value><int>2</int></value>\r
+    </param>\r
+    <param>\r
+      <value><int>2</int></value>\r
+    </param>\r
+  </params>\r
+</methodCall>\r
diff --git a/tools/binmode-rpc-kit/examples/good-3.binmode b/tools/binmode-rpc-kit/examples/good-3.binmode
new file mode 100644 (file)
index 0000000..a0633e8
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/good-3.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/good-3.xml b/tools/binmode-rpc-kit/examples/good-3.xml
new file mode 100644 (file)
index 0000000..4262551
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<methodResponse>\r
+  <params>\r
+    <param>\r
+      <value><int>4</int></value>\r
+    </param>\r
+  </params>\r
+</methodResponse>\r
diff --git a/tools/binmode-rpc-kit/examples/good-4.binmode b/tools/binmode-rpc-kit/examples/good-4.binmode
new file mode 100644 (file)
index 0000000..3d95e77
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/good-4.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/good-4.xml b/tools/binmode-rpc-kit/examples/good-4.xml
new file mode 100644 (file)
index 0000000..06fd1b8
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<methodResponse>\r
+  <fault>\r
+    <value>\r
+      <struct>\r
+        <member>\r
+          <name>faultString</name>\r
+          <value><string>An error occurred</string></value>\r
+        </member>\r
+        <member>\r
+          <name>faultCode</name>\r
+          <value><int>1</int></value>\r
+        </member>\r
+      </struct>\r
+    </value>\r
+  </fault>\r
+</methodResponse>\r
diff --git a/tools/binmode-rpc-kit/examples/good-5.binmode b/tools/binmode-rpc-kit/examples/good-5.binmode
new file mode 100644 (file)
index 0000000..e869c55
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/good-5.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/good-5.xml b/tools/binmode-rpc-kit/examples/good-5.xml
new file mode 100644 (file)
index 0000000..601ff3d
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<methodResponse>\r
+  <params>\r
+    <param>\r
+      <value>\r
+        <array>\r
+          <data>\r
+            <value><string>foo</string></value>\r
+            <value><string>bar</string></value>\r
+            <value><string>foo</string></value>\r
+            <value><string>baz</string></value>\r
+            <value><string>baz</string></value>\r
+            <value><string>bar</string></value>\r
+          </data>\r
+        </array>\r
+      </value>\r
+    </param>\r
+  </params>\r
+</methodResponse>\r
diff --git a/tools/binmode-rpc-kit/examples/good-6.binmode b/tools/binmode-rpc-kit/examples/good-6.binmode
new file mode 100644 (file)
index 0000000..8a7c621
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/good-6.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/good-6.xml b/tools/binmode-rpc-kit/examples/good-6.xml
new file mode 100644 (file)
index 0000000..b0720b8
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<methodResponse>\r
+  <params>\r
+    <param>\r
+      <value><string>Copyright Â© 1995 J. Random Hacker</string></value>\r
+    </param>\r
+  </params>\r
+</methodResponse>\r
diff --git a/tools/binmode-rpc-kit/examples/invalid-1.binmode b/tools/binmode-rpc-kit/examples/invalid-1.binmode
new file mode 100644 (file)
index 0000000..4076dbb
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/invalid-1.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/invalid-2.binmode b/tools/binmode-rpc-kit/examples/invalid-2.binmode
new file mode 100644 (file)
index 0000000..6e5d4b8
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/invalid-2.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/invalid-3.binmode b/tools/binmode-rpc-kit/examples/invalid-3.binmode
new file mode 100644 (file)
index 0000000..ad5e883
--- /dev/null
@@ -0,0 +1 @@
+binmode-rpc:R<\ 2
\ No newline at end of file
diff --git a/tools/binmode-rpc-kit/examples/invalid-4.binmode b/tools/binmode-rpc-kit/examples/invalid-4.binmode
new file mode 100644 (file)
index 0000000..69aa2f4
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/invalid-4.binmode differ
diff --git a/tools/binmode-rpc-kit/examples/invalid-5.binmode b/tools/binmode-rpc-kit/examples/invalid-5.binmode
new file mode 100644 (file)
index 0000000..3899853
Binary files /dev/null and b/tools/binmode-rpc-kit/examples/invalid-5.binmode differ
diff --git a/tools/binmode-rpc-kit/oct2bin b/tools/binmode-rpc-kit/oct2bin
new file mode 100755 (executable)
index 0000000..8fea23f
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+# Turn C-style octal escapes into binary.
+# Call as "echo -n 'ab\0\001cd' | oct2bin > out.binmode".
+
+binmode STDOUT;
+
+while (<>) {
+    s/\\(\d\d\d)/chr(oct($1))/ge;
+    s/\\0/chr(0)/ge;
+    s/\\\\/\\/g;
+    print $_;
+}
diff --git a/tools/interop-server/interop-cgi.c b/tools/interop-server/interop-cgi.c
new file mode 100644 (file)
index 0000000..d079267
--- /dev/null
@@ -0,0 +1,215 @@
+/* A CGI which implements all of the test functions need for an interop
+** endpoint. */
+
+#include <sys/utsname.h>
+#include <errno.h>
+#include <string.h>
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/cgi.h"
+
+#include "version.h"
+
+#include "config.h"  /* information about this build environment */
+
+
+/*=========================================================================
+**  Toolkit Identification
+**=========================================================================
+*/
+
+static xmlrpc_value *
+whichToolkit(xmlrpc_env *   const env, 
+             xmlrpc_value * const param_array, 
+             void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_value * retval;
+
+    /* Parse our argument array. */
+    xmlrpc_parse_value(env, param_array, "()");
+    if (env->fault_occurred)
+        retval = NULL;
+    else {
+        struct utsname utsname;
+
+        int rc;
+        rc = uname(&utsname);
+        if (rc != 0) {
+            xmlrpc_env_set_fault_formatted(env, XMLRPC_INTERNAL_ERROR,
+                                           "uname() failed.  errno=%d (%s)",
+                                           errno, strerror(errno));
+            retval = NULL;
+        } else {
+            /* Assemble our result. */
+            retval = xmlrpc_build_value(env, "{s:s,s:s,s:s,s:s}",
+                                        "toolkitDocsUrl",
+                                        "http://xmlrpc-c.sourceforge.net/",
+                                        "toolkitName", PACKAGE,
+                                        "toolkitVersion", XMLRPC_C_VERSION"+",
+                                        "toolkitOperatingSystem", 
+                                        utsname.sysname);
+        }
+    }
+    return retval;
+}
+
+
+
+static char whichToolkit_help[] =
+"Identify the toolkit used to implement this server.  The operating system "
+"information is based on where the toolkit was compiled, not where it's "
+"currently running.";
+
+
+/*=========================================================================
+**  noInParams
+**=========================================================================
+**  Test a method with no parameters.
+*/
+
+static xmlrpc_value *
+noInParams(xmlrpc_env *   const env, 
+           xmlrpc_value * const param_array, 
+           void *         const user_data ATTR_UNUSED) {
+
+    /* Parse our argument array. */
+    xmlrpc_parse_value(env, param_array, "()");
+    if (env->fault_occurred)
+        return NULL;
+
+    /* Assemble our result. */
+    return xmlrpc_build_value(env, "i", (xmlrpc_int32) 0);
+}
+
+static char noInParams_help[] =
+"A method with no parameters.  Returns an arbitrary int.";
+
+
+/*=========================================================================
+**  Echo Tests
+**=========================================================================
+**  We're lazy--we only implement one actual echo method, but we hook it
+**  up to lots of different names.
+*/
+
+static xmlrpc_value *
+echoValue(xmlrpc_env *   const env, 
+          xmlrpc_value * const param_array, 
+          void *         const user_data ATTR_UNUSED) {
+
+    xmlrpc_value *val;
+
+    /* Parse our argument array. */
+    xmlrpc_parse_value(env, param_array, "(V)", &val);
+    if (env->fault_occurred)
+        return NULL;
+
+    /* Create a new reference (because both our parameter list and our
+    ** return value will be DECREF'd when we return). */
+    xmlrpc_INCREF(val);
+
+    /* Return our result. */
+    return val;
+}
+
+static char echoValue_help[] =
+"Echo an arbitrary XML-RPC value of any type.";
+
+static char echoString_help[] =
+"Echo an arbitrary XML-RPC string.";
+
+static char echoInteger_help[] =
+"Echo an arbitrary XML-RPC integer.";
+
+static char echoBoolean_help[] =
+"Echo an arbitrary XML-RPC boolean value.";
+
+static char echoFloat_help[] =
+"Echo an arbitrary XML-RPC float.";
+
+static char echoStruct_help[] =
+"Echo an arbitrary XML-RPC struct.";
+
+static char echoDate_help[] =
+"Echo an arbitrary XML-RPC date/time value.";
+
+static char echoBase64_help[] =
+"Echo an arbitrary XML-RPC Base64 value.";
+
+static char echoStringArray_help[] =
+"Echo an array of arbitrary XML-RPC strings.";
+
+static char echoIntegerArray_help[] =
+"Echo an array of arbitrary XML-RPC integers.";
+
+static char echoFloatArray_help[] =
+"Echo an array of arbitrary XML-RPC floats.";
+
+static char echoStructArray_help[] =
+"Echo an array of arbitrary XML-RPC structs.";
+
+
+/*=========================================================================
+**  Server Setup
+**=========================================================================
+**  Set up and run our server.
+*/
+
+int 
+main(int     const argc ATTR_UNUSED, 
+     char ** const argv ATTR_UNUSED) {
+
+    /* Process our request. */
+    xmlrpc_cgi_init(XMLRPC_CGI_NO_FLAGS);
+
+    /* Add a method to identify our toolkit. */
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.whichToolkit",
+                               &whichToolkit, NULL,
+                               "S:", whichToolkit_help);
+
+    /* Add a whole bunch of test methods. */
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.noInParams",
+                               &noInParams, NULL,
+                               "i:", noInParams_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoValue",
+                               &echoValue, NULL,
+                               "?", echoValue_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoString",
+                               &echoValue, NULL,
+                               "s:s", echoString_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoInteger",
+                               &echoValue, NULL,
+                               "i:i", echoInteger_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoBoolean",
+                               &echoValue, NULL,
+                               "b:b", echoBoolean_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoFloat",
+                               &echoValue, NULL,
+                               "d:d", echoFloat_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoStruct",
+                               &echoValue, NULL,
+                               "S:S", echoStruct_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoDate",
+                               &echoValue, NULL,
+                               "8:8", echoDate_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoBase64",
+                               &echoValue, NULL,
+                               "6:6", echoBase64_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoStringArray",
+                               &echoValue, NULL,
+                               "A:A", echoStringArray_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoIntegerArray",
+                               &echoValue, NULL,
+                               "A:A", echoIntegerArray_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoFloatArray",
+                               &echoValue, NULL,
+                               "A:A", echoFloatArray_help);
+    xmlrpc_cgi_add_method_w_doc("interopEchoTests.echoStructArray",
+                               &echoValue, NULL,
+                               "A:A", echoStructArray_help);
+
+    xmlrpc_cgi_process_call();
+    xmlrpc_cgi_cleanup();
+
+    return 0;
+}
diff --git a/tools/turbocharger/.cvsignore b/tools/turbocharger/.cvsignore
new file mode 100644 (file)
index 0000000..f3c7a7c
--- /dev/null
@@ -0,0 +1 @@
+Makefile
diff --git a/tools/turbocharger/Makefile b/tools/turbocharger/Makefile
new file mode 100644 (file)
index 0000000..8772c35
--- /dev/null
@@ -0,0 +1,5 @@
+all:
+clean:
+distclean:
+install:
+dep:
\ No newline at end of file
diff --git a/tools/turbocharger/README b/tools/turbocharger/README
new file mode 100644 (file)
index 0000000..4613bfd
--- /dev/null
@@ -0,0 +1,37 @@
+XML-RPC Turbocharger (Experimental)
+===================================
+
+This a hacked copy of mod_gzip. In addition to the usual "gzip" encoding,
+it also handles "deflate" encoding.
+
+When used in conjuction with the xmlrpc-c client, this should reduce your
+outbound XML-RPC network traffic by an amazing amount--compression ratios
+of 10:1 and 30:1 are not unheard of. If you're clever, you should be able
+to use this with just about any Apache-based XML-RPC server.
+
+You can find the standard distribution of mod_gzip here:
+
+  http://www.remotecommunications.com/apache/mod_gzip/
+
+The hacked distribution is installed and used in exactly the same fashion
+as the regular distribution. There's one extra logging directive available:
+
+  %{mod_gzip_compression_format}n   Compression format chosen by client.
+
+Go read the mod_gzip documentation; it should all make sense.
+
+If you want to discuss the XML-RPC Turbocharger, please sign up for the
+xmlrpc-c-devel mailing list at:
+
+  http://xmlrpc-c.sourceforge.net/
+
+This code is highly experimental, and may do some strange things. You'll
+probably need to screw around with mod_gzip for a while until you get
+everything to work. Don't run this on your production web server, OK?
+
+Eric Kidd
+eric.kidd@pobox.com
+
+P.S. The Turbocharger appears to dump core in mod_gzip decides to serialize
+a large response to disk. Do you see what I mean by "experimental" and
+"don't run this on your production web server"? :-)
diff --git a/tools/turbocharger/mod_gzip.c b/tools/turbocharger/mod_gzip.c
new file mode 100644 (file)
index 0000000..490d8ac
--- /dev/null
@@ -0,0 +1,9843 @@
+/* ====================================================================
+ * Copyright (c) 1995-2000 The Apache Group.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the Apache Group
+ *    for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * 4. The names "Apache Server" and "Apache Group" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the Apache Group
+ *    for use in the Apache HTTP server project (http://www.apache.org/)."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Group and was originally based
+ * on public domain software written at the National Center for
+ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
+ * For more information on the Apache Group and the Apache HTTP server
+ * project, please see <http://www.apache.org/>.
+ *
+ */
+
+/* 
+ * mod_gzip.c
+ *
+ * Apache gzip compression module.
+ *
+ * This module adds 'on the fly' compression of HTTP content to
+ * any Apache Web Server. It uses the IETF Content-encoding standard(s).
+ *
+ * It will compress both static files and the output of any CGI
+ * program inclding shell scripts, perl scripts, executables,
+ * PHP used as CGI, etc.
+ *
+ * There is NO client-side software required for using this module
+ * other than any fully HTTP 1.1 compliant user agent.
+ *
+ * Any fully HTTP 1.1 compliant user agent will be able to receive and
+ * automatically decode the compressed content.
+ *
+ * All fully HTTP 1.1 compliant user agents that are capable of receiving
+ * gzip encoded data will indicate their ability to do so by adding the
+ * standard "Accept-Encoding: gzip" field to the inbound request header.
+ * 
+ * This module may be compiled as a stand-alone external 'plug-in'
+ * or be compiled into the Apache core server as a 'built-in' module.
+ *
+ * Sponsor: Remote Communications, Inc. http://www.RemoteCommunications.com/
+ * Authors: Konstantin Balashov, Alex Kosobrukhov and Kevin Kiley.
+ * Contact: info@RemoteCommunications.com
+ *
+ * Initial public release date: 13-Oct-2000
+ *
+ * Miscellaneous release notes:
+ *
+ * THIS IS A COMPLETELY SELF-CONTAINED MODULE. MOD_GZIP.C IS THE
+ * ONY SOURCE CODE FILE THERE IS AND THERE ARE NO MODULE SPECIFIC
+ * HEADER FILES OR THE NEED FOR ANY 3RD PARTY COMPRESSION LIBRARIES.
+ * ALL OF THE COMPRESSION CODE NEEDED BY THIS MODULE IS CONTAINED
+ * WITHIN THIS SINGLE SOURCE FILE.
+ *
+ * Many standard compression libraries are not designed or optimized
+ * for use as real-time compression codecs nor are they guaranteed
+ * to be 'thread-safe'. The internal compression code used by mod_gzip
+ * is all of those things. It is a highly-optimized and thread-safe
+ * implementation of the standard LZ77 + Huffman compression
+ * technique that has come to be known as GZIP.
+ *
+ * MOD_GZIP LOG FORMATS...
+ *
+ * mod_gzip makes a number of statistical items for each transaction
+ * available through the use of Apache's 'LogFormat' directives which
+ * can be specified in the httpd.conf Apache config file
+ *
+ * mod_gzip uses the standard Apache NOTES interface to allow compression
+ * information to be added to the Apache Web Server log files.
+ *
+ * Standard NOTES may be added to Apache logs using the following syntax
+ * in any LogFormat directive...
+ * * %...{Foobar}n:  The contents of note "Foobar" from another module.
+ *
+ * Additional notes about logging compression information...
+ *
+ * The Apache LogFormat directive is unable to actually display
+ * the 'percent' symbol since it is used exclusively as a 'pickup'
+ * character in the formatting string and cannot be 'escaped' so
+ * all logging of compression ratios cannot use the PERCENT symbol.
+ * Use ASCII 'pct.' designation instead for all PERCENTAGE values.
+ *
+ * Example: This will display the compression ratio percentage along
+ * with the standard CLF ( Common Log Format ) information...
+ *
+ * Available 'mod_gzip' compression information 'notes'...
+ *
+ * %{mod_gzip_result}n - A short 'result' message. Could be OK or DECLINED, etc.
+ * %{mod_gzip_input_size}n - The size ( in bytes ) of the requested object.
+ * %{mod_gzip_output_size}n - The size ( in bytes ) of the compressed version.
+ * %{mod_gzip_compression_ration}n - The compression rate achieved.
+ *
+ *  LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info1
+ *  LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_result}n In:%{mod_gzip_input_size}n Out:%{mod_gzip_output_size}n:%{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info2
+ *
+ * If you create your own custom 'LogFormat' lines don't forget that
+ * the entire LogFormat line must be encased in quote marks or you
+ * won't get the right results. The visible effect of there not being
+ * and end-quote on a LogFormat line is that the NAME you are choosing
+ * for the LogFormat line is the only thing that will appear in the
+ * log file that tries to use the unbalanced line.
+ *
+ * Also... when using the %{mod_gzip_xxxxx}n note references in your
+ * LogFormat line don't forget to add the lowercase letter 'n' after
+ * the closing bracket to indicate that this is a module 'note' value.
+ *
+ * Once a LogFormat directive has been added to your httpd.conf file
+ * which displays whatever level of compression information desired
+ * simply use the 'name' associated with that LogFormat line in
+ * the 'CustomLog' directive for 'access.log'.
+ *
+ * Example: The line below simply changes the default access.log format
+ * for Apache to the special mog_gzip information record defined above...
+ * CustomLog logs/access.log common
+ *
+ *  CustomLog logs/access.log common_with_mod_gzip_info2
+ *
+ * Using the 'common_with_mod_gzip_info1' LogFormat line for Apache's
+ * normal access.log file produces the following results in the access.log
+ * file when a gigantic 679,188 byte online CD music collection HTML
+ * document called 'music.htm' is requested and the Server delivers the
+ * file via mod_gzip compressed 93 percent down to only 48,951 bytes...
+ *
+ * 216.20.10.1 [12/Oct...] "GET /music.htm HTTP/1.1" 200 48951 mod_gzip: 93pct.
+ *
+ * The line below shows what will appear in the Apache access.log file
+ * if the more detailed 'common_with_mod_gzip_info2' LogFormat line is used.
+ * The line has been intentionally 'wrapped' for better display below
+ * but would normally appear as a single line entry in access.log.
+ *
+ * 216.20.10.1 [12/Oct...] "GET /music.htm HTTP/1.1" 200 48951
+ *                          mod_gzip: OK In:679188 Out:48951:93pct.
+ *
+ * The 'OK' result string shows that the compression was successful.
+ * The 'In:' value is the size (in bytes) of the requested file and
+ * the 'Out:' value is the size (in bytes) after compression followed
+ * by a colon and a number showing that the document was compressed
+ * 93 percent before being returned to the user.
+ *
+ * Please NOTE that if you add any ASCII strings to your LogFormat
+ * string then they will appear in your log file regardless of
+ * whether this module was actually 'called' to process the
+ * transaction or not. If the module was not called to handle the
+ * transaction then the places where the statistical information
+ * associated with the 'NOTES' references would normally appear
+ * will be filled in with 'dashes' to denote 'no value available'.
+ *
+ * MOD_GZIP RUNTIME DEBUG...
+ *
+ * If you set your default Apache logging level to 'LogLevel debug'
+ * in your httpd.conf file then this module will add certain
+ * diagnostic debug messages to your error log for each and every
+ * transaction that is actually passed to the module.
+ *
+ * If Apache does not 'call' this module to handle a particular
+ * transaction then no special log information will appear in
+ * your error log(s) for that transaction.
+ *
+ * MOD_GZIP CONFIGURATION DIRECTIVES...
+ *
+ * The section that follows is a sample mod_gzip configuration
+ * section that will provide basic compression of all static
+ * TEXT and HTML files as well as dynamic compression of most
+ * standard CGI including Shell scripts, Perl, PHP, etc.
+ *
+ * The configuration directives themselves are documented in more
+ * detail in the README and INSTALL files that accompany this module.
+ *
+ * You should be able to simply 'cut and paste' the follwing section
+ * directly into the BOTTOM of your current httpd.conf Apache
+ * configuration file and be able to start using mod_gzip immediately.
+ *
+
+#
+# MOD_GZIP Configuration Directives
+#
+# All you should have to do to get up and running using
+# mod_gzip with some basic STATIC and DYNAMIC compression
+# capabilites is copy the mod_gzip dynamic library to your
+# ../modules directory and then add this entire example
+# configuration section to the BOTTOM of your httpd.conf file.
+#
+# Add this entire section including all lines down to where
+# it says '# End of MOD_GZIP Configuration Directives'.
+#
+# The LoadModule command is included here for clarity
+# but you may want to move it the the BOTTOM of your
+# current LoadModule list in httpd.conf.
+#
+# Change the 'mod_gzip_temp_dir' to the name of a directory
+# on your machine where temporary workfiles can be created
+# and destroyed. This directory MUST be readable/writable
+# by the Server itself while it is running. If the directory
+# does not exist you must create it yourself with the right
+# permissions before running the Server.
+#
+# If no 'mod_gzip_temp_dir' is specified then the default location
+# for temporary workfiles will be 'ServerRoot' directory.
+#
+# The special mod_gzip log formats are, of course, optional.
+#
+# You must, of course, load the right module name for your OS
+# so make sure the correct 'LoadModule' command is uncommented
+# directly below...
+
+# Load Win32 module...
+LoadModule gzip_module modules/ApacheModuleGzip.dll
+
+# Load UNIX module...
+# LoadModule gzip_module modules/mod_gzip.so
+
+LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info1
+LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_result}n In:%{mod_gzip_input_size}n Out:%{mod_gzip_output_size}n:%{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info2
+
+# NOTE: This 'CustomLog' directive shows how to set your access.log file
+# to use the mod_gzip format but please remember that for every 'CustomLog'
+# directive that Apache finds in httpd.conf there will be corresponding
+# line of output in the access.log file. If you only want ONE line of
+# results in access.log for each transaction then be sure to comment out
+# any other 'CustomLog' directives so that this is the only one.
+
+CustomLog logs/access.log common_with_mod_gzip_info2
+
+# Runtime control directives...
+
+mod_gzip_on                 Yes
+mod_gzip_do_cgi             Yes
+mod_gzip_do_static_files    Yes
+mod_gzip_minimum_file_size  300
+mod_gzip_maximum_inmem_size 60000
+mod_gzip_keep_workfiles     No
+mod_gzip_temp_dir           "C:/Program Files/Apache Group/Apache/temp"
+
+# Item lists...
+#
+# Item names can be any one of the following...
+#
+# cgi-script - A valid 'handler' name
+# text/*     - A valid MIME type name ( '*' wildcard allowed )
+# .phtml     - A valid file type extension
+
+# Dynamic items...
+#
+# NOTE: FOR NOW ALL DYNAMIC ITEMS SHOULD BE
+# DECLARED BEFORE ANY STATIC ITEMS TO PREVENT
+# PICKUP CONFLICTS. IF YOU USE !cgi-script
+# BE SURE IT IS DECLARED BEFORE ANY text/*
+# MIME TYPE ENTRIES.
+#
+# The items listed here are the types of dynamic
+# output that will be compressed...
+#
+# Dynamic items MUST have the "!" BANG character
+# on the front of the item name.
+#
+mod_gzip_item_include !cgi-script
+mod_gzip_item_include !.php
+mod_gzip_item_include !.php3
+mod_gzip_item_include !.phtml
+
+# Static items...
+#
+# The items listed here are the types of static
+# files that will be compressed...
+#
+# NOTE: FOR NOW ALL STATIC INCLUDES MUST
+# COME AFTER DYNAMIC INCLUDES TO PREVENT
+# PICKUP CONFLICTS
+#
+mod_gzip_item_include text/*
+
+# Uncomment this line to compress graphics
+# when graphics compression is allowed...
+#mod_gzip_item_include image/*
+
+
+# Exclusions... MIME types and FILE types...
+#
+# The items listed here will be EXCLUDED from
+# any attempt to apply compression...
+#
+mod_gzip_item_exclude .js
+mod_gzip_item_exclude .css
+
+# Exclusions... HTTP support levels...
+#
+# By specifying a certain minimum level of HTTP support
+# certain older user agents ( browsers ) can be
+# automatically excluded from receiving compressed data.
+#
+# The item value should be in the same HTTP numeric format
+# that Apache uses to designate HTTP version levels.
+#
+# 1001 = HTTP/1.1
+#
+# So 'mod_gzip_min_http 1001' means that a requesting
+# user agent ( browser ) must report a minimum HTTP support
+# level of 1.1 or it will not receive any compressed data.
+#
+mod_gzip_min_http 1001
+
+# Debugging...
+#
+# If your Apache 'LogLevel' is set to 'debug' then
+# mod_gzip will add some diagnostic and compression
+# information to your error.log file for each request
+# that is processed by mod_gzip.
+#
+# LogLevel debug
+
+# End of MOD_GZIP Configuration Directives
+
+ * End of inline comments
+ */
+
+#include <stdlib.h>
+/*
+ * Apache headers...
+ */
+
+#define CORE_PRIVATE
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_protocol.h"
+#include "util_script.h"
+
+/*
+ * Add this header for ap_server_root[ MAX_STRING_LEN ] global...
+ *
+ * #include "http_conf_globals.h"
+ *
+ * ...or just include what we need from http_conf_globals.h
+ * since that is, in fact, only 1 item at this time.
+ */
+extern API_VAR_EXPORT char ap_server_root[ MAX_STRING_LEN ];
+
+/*
+ * Add this header to get 'ap_update_mtime()' prototype...
+ *
+ * #include "http_request.h"
+ *
+ * ...or just include what we need from http_request.h since
+ * that is, in fact, only 1 item at this time.
+ */
+extern API_EXPORT(time_t)
+ap_update_mtime(request_rec *r, time_t dependency_mtime);
+
+/*
+ * Version information...
+ *
+ * Since this product is 'married' to the ASF Apache Web Server
+ * the version numbers should always 'match' the changing
+ * version numbers of Apache itself so users can be sure
+ * they have the 'right' module. This allows us to move the
+ * version numbers either backwards or forwards in case issues
+ * arise which require specific versions of mod_gzip for
+ * specific versions of Apache.
+ *
+ * The original code was first tested against the Apache 1.3.14
+ * release but should be compatible with the entire 1.3.x series.
+ * If earlier 1.3.x versions of Apache required special versions
+ * then the mod_gzip version number will still match the Apache
+ * version number ( As in... mod_gzip v1.3.12.1, if needed ).
+ *
+ * If a special version is required for Apache 2.0 then the
+ * version number(s) will change to match release numbers in
+ * that series. ( As in... mod_gzip v 2.0.1.1, etc. ).
+ *
+ * The first 3 numbers of the version are always the equivalent
+ * Apache release numbers. The fourth number is always the actual
+ * mod_gzip 'build' number for that version of Apache.
+ */
+
+char mod_gzip_version[] = "1.3.14.5"; /* Global version string */
+
+/*
+ * Declare the NAME by which this module will be known.
+ * This is the NAME that will be used in LoadModule command(s).
+ */
+extern module MODULE_VAR_EXPORT gzip_module;
+
+/*
+ * Allow this module to 'read' config information from
+ * ( and interact with ) the 'real' mod_cgi module...
+ */
+extern module cgi_module;
+
+/*
+ * Some compile-time code inclusion switches...
+ */
+
+/*
+ * Turn MOD_GZIP_ALLOWS_INTERNAL_COMMANDS switch ON to allow
+ * information requests to be sent via any standard browser.
+ */
+
+#define MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
+
+/*
+ * Turn MOD_GZIP_USES_APACHE_LOGS switch ON to include the
+ * code that can update Apache logs with compression information.
+ */
+
+#define MOD_GZIP_USES_APACHE_LOGS
+
+ /*
+  * Turn MOD_GZIP_USES_AP_SEND_MMAP switch ON to use the
+  * ap_send_mmap() method for transmitting data. If this
+  * switch is OFF then the default is to use ap_rwrite().
+  * This might need to be platform specific at some point.
+  */
+
+#define MOD_GZIP_USES_AP_SEND_MMAP
+
+/*
+ * Turn MOD_GZIP_DEBUG1 switch ON for verbose diags.
+ * This is normally OFF by default and should only be
+ * used for diagnosing problems. The log output is
+ * VERY detailed and the log files will be HUGE.
+ */
+
+/*
+#define MOD_GZIP_DEBUG1
+*/
+
+/*
+ * Some useful instance globals...
+ */
+
+#ifndef MOD_GZIP_MAX_PATH_LEN
+#define MOD_GZIP_MAX_PATH_LEN 512
+#endif
+
+char mod_gzip_temp_dir[ MOD_GZIP_MAX_PATH_LEN + 2 ];
+
+long mod_gzip_iusn = 0; /* Instance Unique Sequence Number */
+
+long mod_gzip_maximum_inmem_size = 60000L;
+long mod_gzip_minimum_file_size  = 300L;
+
+#ifdef WIN32
+char mod_gzip_dirsep[]="\\"; /* Dir separator is a backslash for Windows */
+#else /* !WIN32 */
+char mod_gzip_dirsep[]="/";  /* Dir separator is a forward slash for UNIX */
+#endif /* WIN32 */
+
+/*
+ * The Compressed Object Cache control structure...
+ */
+
+#define MOD_GZIP_SEC_ONE_DAY 86400  /* Total seconds in one day */
+#define MOD_GZIP_SEC_ONE_HR  3600   /* Total seconds in one hour */
+
+#define MOD_GZIP_DEFAULT_CACHE_SPACE 5
+#define MOD_GZIP_DEFAULT_CACHE_MAXEXPIRE MOD_GZIP_SEC_ONE_DAY
+#define MOD_GZIP_DEFAULT_CACHE_EXPIRE    MOD_GZIP_SEC_ONE_HR
+#define MOD_GZIP_DEFAULT_CACHE_LMFACTOR (0.1)
+#define MOD_GZIP_DEFAULT_CACHE_COMPLETION (0.9)
+
+struct mod_gzip_cache_conf {
+
+    const char *root;             /* The location of the cache directory */
+    off_t       space;            /* Maximum cache size (in 1024 bytes) */
+    char        space_set;
+    time_t      maxexpire;        /* Maximum time to keep cached files (secs) */
+    char        maxexpire_set;
+    time_t      defaultexpire;    /* Default time to keep cached file (secs) */
+    char        defaultexpire_set;
+    double      lmfactor;         /* Factor for estimating expires date */
+    char        lmfactor_set;
+    time_t      gcinterval;       /* Garbage collection interval (secs) */
+    char        gcinterval_set;
+    int         dirlevels;        /* Number of levels of subdirectories */
+    char        dirlevels_set;
+    int         dirlength;        /* Length of subdirectory names */
+    char        dirlength_set;
+};
+
+/*
+ * The Inclusion/Exclusion map item structure...
+ */
+
+#define MOD_GZIP_IMAP_MAXNAMES   256
+#define MOD_GZIP_IMAP_MAXNAMELEN 90
+
+#define MOD_GZIP_IMAP_ISMIME     1
+#define MOD_GZIP_IMAP_ISEXT      2
+#define MOD_GZIP_IMAP_ISHANDLER  3
+
+#define MOD_GZIP_IMAP_STATIC1    9001
+#define MOD_GZIP_IMAP_DYNAMIC1   9002
+#define MOD_GZIP_IMAP_DECLINED1  9003
+
+typedef struct {
+
+    int  include; /* 1=Include 0=Exclude */
+    int  type;    /* _ISMIME, _ISEXT, _ISHANDLER, etc. */
+    int  action;  /* _STATIC1, _DYNAMIC1, etc. */
+
+    char name[ MOD_GZIP_IMAP_MAXNAMELEN + 2 ];
+
+} mod_gzip_imap;
+
+/*
+ * The primary module configuration record...
+ */
+
+typedef struct {
+
+    struct mod_gzip_cache_conf cache; /* Compressed Object Cache control */
+
+    int  req;                /* 1=mod_gzip handles requests 0=No */
+    char req_set;            /* Mirrors the 'req' flag */
+    int  do_static_files;    /* 1=Yes 0=No */
+    int  do_cgi;             /* 1=Yes 0=No */
+    int  keep_workfiles;     /* 1=Keep workfiles 0=No */
+    int  min_http;           /* Minimum HTTP level ( 1001=HTTP/1.1 ) */
+    long minimum_file_size;  /* Minimum size in bytes for compression attempt */
+    long maximum_inmem_size; /* Maximum size in bytes for im-memory compress */
+
+    /* Inclusion/Exclusion list(s)... */
+
+    int imap_total_entries;
+
+    mod_gzip_imap imap[ MOD_GZIP_IMAP_MAXNAMES + 1 ];
+
+} mod_gzip_conf;
+
+/*
+ * The GZP request control structure...
+ */
+
+#define GZIP_FORMAT    (0)
+#define DEFLATE_FORMAT (1)
+
+typedef struct _GZP_CONTROL {
+
+    int   decompress;  /* 0=Compress 1=Decompress */
+
+    int   compression_format;  /* GZIP_FORMAT or DEFLATE_FORMAT */
+
+    /* Input control... */
+
+    int   input_ismem;         /* Input source is memory buffer, not file */
+    char *input_ismem_ibuf;    /* Pointer to input memory buffer */
+    long  input_ismem_ibuflen; /* Total length of input data */
+
+    char  input_filename[ MOD_GZIP_MAX_PATH_LEN + 2 ]; /* Input file name */
+
+    /* Output control... */
+
+    int   output_ismem;         /* Output source is memory buffer, not file */
+    char *output_ismem_obuf;    /* Pointer to output memory buffer */
+    long  output_ismem_obuflen; /* Maximum length of output data buffer */
+
+    char  output_filename[ MOD_GZIP_MAX_PATH_LEN + 2 ]; /* Output file name */
+
+    /* Results... */
+
+    int   result_code; /* Result code */
+    long  bytes_out;   /* Total number of compressed output bytes */
+
+} GZP_CONTROL;
+
+/*
+ * Forward prototypes for internal routines...
+ */
+
+int gzp_main( GZP_CONTROL *gzp ); /* Primary GZP API entry point */
+
+int mod_gzip_request_handler( request_rec *r );
+int mod_gzip_cgi_handler( request_rec *r );
+int mod_gzip_static_file_handler( request_rec *r );
+int mod_gzip_prepare_for_dynamic_call( request_rec *r );
+int mod_gzip_imap_show_items( mod_gzip_conf *mgc );
+int mod_gzip_get_action_flag( request_rec *r, mod_gzip_conf *conf );
+int mod_gzip_ismatch( char *s1, char *s2, int len1, int haswilds );
+
+FILE *mod_gzip_open_output_file(
+request_rec *r,
+char *output_filename,
+int  *rc
+);
+
+int mod_gzip_create_unique_filename(
+mod_gzip_conf *mgc,
+char *target,
+int targetmaxlen
+);
+
+int mod_gzip_encode_and_transmit(
+request_rec *r,
+char        *source,
+int          source_is_a_file,
+long         input_size,
+int          nodecline
+);
+
+
+#ifdef MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
+
+int mod_gzip_send_html_command_response(
+request_rec *r, /* Request record */
+char *tmp,      /* Response to send */
+char *ctype     /* Content type string */
+);
+
+#endif /* MOD_GZIP_ALLOWS_INTERNAL_COMMANDS */
+
+/*
+ * Module routines...
+ */
+
+#ifdef MOD_GZIP_DEBUG1
+
+void mod_gzip_printf( const char *fmt, ... )
+{
+ int   l;
+ FILE *log;
+
+ va_list ap;
+
+ char logname[256];
+ char log_line[4096];
+
+ /* Start... */
+
+ /* If UNIX  then mod_gzip_dirsep = '/' Backward slash */
+ /* If WIN32 then mod_gzip_dirsep = '\' Forward  slash */
+
+ #ifdef FUTURE_USE
+ /*
+ For now we need both startup and runtime diags in the same
+ log so it all goes to ServerRoot. 'mod_gzip_temp_dir' name
+ isn't even valid until late in the startup process so we
+ have to write to ServerRoot anyway until temp dir is known.
+ */
+ if ( strlen(mod_gzip_temp_dir) ) /* Use temp directory ( if specified )... */
+   {
+    sprintf( logname, "%s%smod_gzip.log", mod_gzip_temp_dir, mod_gzip_dirsep );
+   }
+ else /* Just use 'ap_server_root' Apache ServerRoot directory... */
+   {
+    sprintf( logname, "%s%smod_gzip.log", ap_server_root, mod_gzip_dirsep );
+   }
+ #endif /* FUTURE_USE */
+
+ /* Just use ServerRoot for now... */
+ sprintf( logname, "%s%smod_gzip.log", ap_server_root, mod_gzip_dirsep );
+
+ log = fopen( logname,"a" );
+
+ if ( !log ) /* Log file did not open... */
+   {
+    /* Just turn and burn... */
+
+    return; /* Void return */
+   }
+
+ /* Get the variable parameter list... */
+
+ va_start( ap, fmt );
+
+ l = vsprintf(log_line, fmt, ap);
+
+ /* See if we need to add LF... */
+
+ if ( l > 0 )
+   {
+    if ( log_line[l-1] != '\n' )
+      {
+       log_line[l]='\n';
+       l++;
+      }
+
+    log_line[l+1] = 0;
+   }
+
+ fprintf( log, "%s", log_line );
+
+ fclose( log );
+
+ va_end(ap); /* End session */
+
+ return; /* Void return */
+
+}/* End of log_d() */
+
+void mod_gzip_hexdump( char *buffer, int buflen )
+{
+ int i,o1,o2,o3;
+
+ int len1;
+ int len2;
+
+ char ch1;
+ char ch2;
+ char s[40];
+ char l1[129];
+ char l2[129];
+ char l3[300];
+
+ long offset1=0L;
+
+ /* Start... */
+
+ o1=0;
+ o2=0;
+ o3=0;
+
+ l1[0] = 0;
+ l2[0] = 0;
+ l3[0] = 0;
+
+ offset1 = 0;
+
+ for ( i=0; i<buflen; i++ )
+    {
+     ch1 = (char) *buffer++;
+
+     /*------------------------------------------------------------*/
+     /* WARNING: UNIX hates anything non-printable. It can mess    */
+     /*          up the terminal output by trying to use SLASH     */
+     /*          ESCAPE substitutions...                           */
+     /*------------------------------------------------------------*/
+     /* DOUBLE WARNING!: We MUST mask the per-cent char (37 dec)   */
+     /* and the 'backslash' char ( 92 decimal ) or the UNIX        */
+     /* STDIO calls could CRASH. They are just brain-dead enough   */
+     /* to actually try to respond to these chars in the output    */
+     /* stream and convert them to HEX equivalents which could     */
+     /* lengthen the output string(s) and CRASH the output buffer. */
+     /*------------------------------------------------------------*/
+
+     /* ASTERISK         = ASC 42 */
+     /* LEFT APOSTROPHE  = ASC 96 */
+     /* RIGHT APOSTROPHE = ASC 39 */
+     /* PERIOD           = ASC 46 */
+     /* CR DUMP SYMBOL   = ASC 67 ( The letter C ) */
+     /* LF DUMP SYMBOL   = ASC 76 ( The letter L ) */
+
+     #define DUMPIT_ASTERISK    42
+     #define DUMPIT_LAPOSTROPHE 96
+     #define DUMPIT_RAPOSTROPHE 39
+     #define DUMPIT_PERIOD      46
+     #define DUMPIT_CR          67
+     #define DUMPIT_LF          76
+
+     #ifdef MASK_ONLY_CERTAIN_CHARS
+          if ( ch1 ==  0 ) ch2 = DUMPIT_PERIOD;
+     else if ( ch1 == 13 ) ch2 = DUMPIT_CR;
+     else if ( ch1 == 10 ) ch2 = DUMPIT_LF;
+     else if ( ch1 ==  9 ) ch2 = DUMPIT_LAPOSTROPHE;
+     else                  ch2 = ch1;
+     #endif
+
+     #define MASK_ALL_NON_PRINTABLE_CHARS
+     #ifdef  MASK_ALL_NON_PRINTABLE_CHARS
+
+     /* Mask all control chars and high ends chars for UNIX or */
+     /* TTY console screws up... */
+
+          if ( ch1 == 13 ) ch2 = DUMPIT_CR;
+     else if ( ch1 == 10 ) ch2 = DUMPIT_LF;
+     else if ( ch1 <  32 ) ch2 = DUMPIT_PERIOD;
+     else if ( ch1 >  126) ch2 = DUMPIT_LAPOSTROPHE;
+     else if ( ch1 == 37 ) ch2 = DUMPIT_ASTERISK; /* Mask PERCENT   for UNIX */
+     else if ( ch1 == 92 ) ch2 = DUMPIT_ASTERISK; /* Mask BACKSLASH for UNIX */
+     else                  ch2 = ch1;
+
+     /* ENDIF on MASK_ALL_NON_PRINTABLE_CHARS */
+     #endif
+
+     l2[o2++] = ch2;
+
+     sprintf( s, "%02X", ch1 );
+
+     if ( strlen(s) > 2 ) s[2]=0; /* Prevent overflow */
+
+     len1 = strlen(s);
+     len2 = strlen(l1);
+
+     if ( strlen(l1) < (sizeof(l1) - (len1+1)) )
+       {
+        strcat( l1, s   );
+        strcat( l1, " " );
+       }
+
+     if ( o2 >= 16 )
+       {
+        l2[o2]=0;
+
+        mod_gzip_printf( "%6lu| %-49.49s| %-16.16s |\n", offset1, l1, l2 );
+
+        offset1 += o2;
+
+        o1=0;
+        o2=0;
+        o3=0;
+
+        l1[0] = 0;
+        l2[0] = 0;
+        l3[0] = 0;
+       }
+
+    }/* End 'for( i=0; i<buflen; i++ )' loop... */
+
+ /* Print remainder ( if anything ) */
+
+ if ( o2 > 0  )
+   {
+    l2[o2]=0;
+
+    mod_gzip_printf( "%6lu| %-49.49s| %-16.16s |\n", offset1, l1, l2 );
+
+    offset1 += o2;
+
+    o1 = o2 = o3 = 0;
+
+    l1[0] = 0;
+    l2[0] = 0;
+    l3[0] = 0;
+   }
+
+}/* End of mod_gzip_hexdump() */
+
+#endif /* MOD_GZIP_DEBUG1 */
+
+static void mod_gzip_init( server_rec *server, pool *p )
+{
+    /*
+     * The module initialization procedure...
+     */
+
+    FILE *fh1;
+    char filename[ 512 ];
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_init()";
+    #endif
+
+    mod_gzip_conf *mgc;
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry...\n", cn );
+    #endif
+
+    /*
+     * Set some instance specific globals...
+     *
+     * The default 'temp' dir, lacking an httpd.conf config file
+     * override, is the Apache 'ServerRoot'. Don't assume that /logs
+     * dir exists because some Apache installations just use syslog
+     * or stderr as their log output target.
+     *
+     * On most Apache installations 'ServerRoot' is automatically
+     * readable/writable by the Server while it is running.
+     *
+     * On systems where it is not there MUST be an override
+     * in the httpd.conf file.
+     *
+     * See the comments regarding the 'mod_gzip_temp_dir' directive
+     * in the httpd.conf configuration file.
+     */
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(server->module_config, &gzip_module);
+
+    /* Make sure we can read/write the temp directory... */
+
+    sprintf( filename, "%s%smod_gzip.id", mgc->cache.root, mod_gzip_dirsep );
+
+    fh1 = fopen( filename, "wb" );
+
+    if ( !fh1 ) /* Write an ERROR to console and to log(s)... */
+      {
+       fprintf( stderr, "mod_gzip: Cannot read/write dir/file [%s]\n",filename);
+       fprintf( stderr, "mod_gzip: Make sure the directory exists and that the Server\n");
+       fprintf( stderr, "mod_gzip: has read/write permission(s) for the directory.\n");
+       fprintf( stderr, "mod_gzip: See the 'mod_gzip_temp_dir' configuration notes.\n");
+
+       /* This is a startup ERROR and has to be fixed... */
+
+       ap_log_error( "",0,APLOG_NOERRNO|APLOG_ERR, server,
+       "mod_gzip: Cannot read/write dir/file [%s]", filename);
+       ap_log_error( "",0,APLOG_NOERRNO|APLOG_ERR, server,
+       "mod_gzip: Make sure the directory exists and that the Server");
+       ap_log_error( "",0,APLOG_NOERRNO|APLOG_ERR, server,
+       "mod_gzip: has read/write permission(s) for the directory.");
+       ap_log_error( "",0,APLOG_NOERRNO|APLOG_ERR, server,
+       "mod_gzip: See the 'mod_gzip_temp_dir' configuration notes.");
+      }
+    else /* File opened OK... just add some data and close it... */
+      {
+       /*
+        * Since this is just a MARK file we could simply wipe
+        * it out but might as well print the actual version
+        * number into it and leave it there in case there is
+        * any question about which version is actually running.
+        */
+
+       fprintf( fh1, "mod_gzip version %s\n", mod_gzip_version );
+       fclose( fh1 );
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_imap_show_items( (mod_gzip_conf *) mgc ); /* Show item list */
+    mod_gzip_printf( "%s: Exit > return( void ) >\n", cn );
+    mod_gzip_printf( "\n" ); /* Separator for log file */
+    #endif
+
+}/* End of mod_gzip_init() */
+
+int mod_gzip_strnicmp( char *s1, char *s2, int len1 )
+{
+ /* Behaves just like strnicmp() but IGNORES differences */
+ /* between FORWARD or BACKWARD slashes in a STRING...   */
+ /* Also uses straight pointers and avoids stdlib calls. */
+
+ int i;
+ char ch1;
+ char ch2;
+
+ /* WARNING! We MUST have a check for 'NULL' on the pointer(s) */
+ /*          themselves or we might GP ( like NETSCAPE does )  */
+ /*          if a 'NULL' pointer is passed to this routine...  */
+
+ if ( ( s1 == 0 ) || ( s2 == 0 ) )
+   {
+    /* SAFETY! If pointer itself if NULL       */
+    /* don't enter LOOP or NETSCAPE will GP... */
+
+    return( 1 ); /* Return '1' for NOMATCH...  */
+   }
+
+ for ( i=0; i<len1; i++ )
+    {
+     if ( ( *s1 == 0 ) || ( *s2 == 0 ) ) return( 1 ); /* No match! */
+
+     ch1 = *s1;
+     ch2 = *s2;
+
+     if ( ch1 > 96 ) ch1 -= 32;
+     if ( ch2 > 96 ) ch2 -= 32;
+
+     if ( ch1 == '/' ) ch1 = '\\';
+     if ( ch2 == '/' ) ch2 = '\\';
+
+     if ( ch1 != ch2 ) return( 1 ); /* No match! */
+
+     s1++;
+     s2++;
+
+    }/* End 'i' loop */
+
+ /* If we make it to here then everything MATCHED! */
+
+ return( 0 ); /* MATCH! */
+
+}/* End mod_gzip_strnicmp() */
+
+extern API_VAR_EXPORT module *top_module;
+
+struct _table {
+    array_header a;
+#ifdef MAKE_TABLE_PROFILE
+    void *creator;
+#endif
+};
+typedef struct _table _table;
+
+const char *mod_gzip_isscript( request_rec *r, _table *t, const char *key)
+{
+    /*
+     * Get a 'handler' name for a MIME type right out of
+     * the Apache 'Action' table(s)...
+     *
+     * Example:
+     *
+     * If "key" is "applications/x-httpd-php3"
+     * then this search will return "/php3/php.exe"
+     * or whatever the equivalent PHP executable
+     * pathname is as specified by an 'Action' statement
+     * in the httpd.conf configuration file.
+     *
+     * This pathname might still have 'aliases' in it
+     * so we will have to consult with mod_alias
+     * following this call and get any aliases converted.
+     */
+
+    table_entry *elts =
+    (table_entry *) t->a.elts;
+    int i;
+
+    char cn[]="mod_gzip_isscript()";
+
+    /*
+     * Start...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry...\n",cn);
+    mod_gzip_printf( "%s: key=[%s]\n",cn,key );
+    #endif
+
+    if ( key == NULL )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: 'key' has no length\n",cn);
+       mod_gzip_printf( "%s: Exit > return( NULL ) >\n",cn);
+       #endif
+
+       if ( r->server->loglevel == APLOG_DEBUG )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "%s: Search key is NULL.",cn);
+         }
+
+       return NULL;
+      }
+
+    for (i = 0; i < t->a.nelts; ++i)
+       {
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf(
+        "%s: i=%4.4d Comparing [%s] with elts.key[%s].val[%s]\n",
+        cn, i, key, elts[i].key, elts[i].val );
+        #endif
+
+        if ( r->server->loglevel == APLOG_DEBUG )
+          {
+           ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "%s: i=%4.4d Comparing [%s] with elts.key[%s].val[%s]",
+           cn, i, key, elts[i].key, elts[i].val );
+          }
+
+        if (!strcasecmp(elts[i].key, key))
+          {
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: MATCH FOUND!",cn);
+           mod_gzip_printf( "%s: Exit > return(%s) >\n",cn,elts[i].val);
+           #endif
+
+           if ( r->server->loglevel == APLOG_DEBUG )
+             {
+              ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+              "%s: MATCH FOUND...",cn);
+             }
+
+           return elts[i].val;
+          }
+
+       }/* End 'i' loop */
+
+    if ( r->server->loglevel == APLOG_DEBUG )
+      {
+       ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+       "%s: NO MATCH FOUND...",cn);
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: NO MATCH FOUND!\n",cn);
+    mod_gzip_printf( "%s: Exit > return( NULL ) >\n",cn);
+    #endif
+
+    return NULL;
+
+}/* End of 'mod_gzip_isscript()' */
+
+typedef struct {
+  table *action_types;       /* Added with Action... */
+  char *scripted[METHODS];   /* Added with Script... */
+  array_header *xmethods;    /* Added with Script -- extension methods */
+} mod_actions_local_config;
+
+int mod_gzip_run_mod_action( request_rec *r )
+{
+    module *modp;
+    int count=0;
+    int pass=0;
+
+    mod_actions_local_config *mod_actions_conf;
+
+    const char *t=0;
+    const char *action=0;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_run_mod_action()";
+    #endif
+
+    #ifdef MOD_GZIP_FUTURE_USE
+    const handler_rec *handp;
+    #endif
+
+    /* Currently 9 possible 'event' handlers. */
+    /* Actual content handler in a module is 'extra'. */
+    #define MOD_GZIP_NMETHODS 9
+
+    /*
+     * Start...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry...\n",cn);
+    mod_gzip_printf( "%s: *IN: r->uri         =[%s]\n", cn, r->uri );
+    mod_gzip_printf( "%s: *IN: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
+    mod_gzip_printf( "%s: *IN: r->filename    =[%s]\n", cn, r->filename );
+    mod_gzip_printf( "%s: r->content_type     =[%s]\n", cn,r->content_type);
+    mod_gzip_printf( "%s: r->handler          =[%s]\n", cn,r->handler);
+    #endif
+
+    for ( modp = top_module; modp; modp = modp->next )
+       {
+        /* modp->name list will look like this... */
+        /*--------------------*/
+        /* 00 [mod_gzip.c]    */
+        /* 01 [mod_isapi.c]   */
+        /* 02 [mod_setenv.c]  */
+        /* 02 [mod_actions.c] */
+        /*    ............... */
+        /*    ............... */
+        /* 18 [mod_so.c]      */
+        /* 19 [http_core.c]   <- Always bottom of list (last one called) */
+        /*--------------------*/
+
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: count=%4.4d modp = %10.10ld modp->name=[%s]\n",
+        cn,count,(long)modp, modp->name );
+        #endif
+
+        if ( mod_gzip_strnicmp( (char *) modp->name, "mod_actions.c", 13 ) == 0 )
+        {
+
+        /* Module information... */
+
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: ++++++++++ MODULE FOUND!...\n",cn);
+        mod_gzip_printf( "%s: ++++++++++ modp->module_index = %d\n",cn,(int)modp->module_index);
+        #endif
+
+        /* Get a pointer to the module configuration data... */
+
+        mod_actions_conf = (mod_actions_local_config *)
+        ap_get_module_config(r->per_dir_config, modp );
+
+        /* Get script name... */
+
+        /* Make 2 passes if necessary. If we don't find a   */
+        /* program name associated with MIME type first     */
+        /* then punt and look for a program name associated */
+        /* with the r->handler name such as [php-script]    */
+
+        for ( pass = 0; pass < 2; pass++ )
+           {
+            if ( pass == 0 ) /* Check r->content_type first */
+              {
+               /* This is the first pass... */
+
+               /* Set 'action' search key to 'r->content_type' */
+               /* so we search for [application/x-httpd-php3]  */
+
+               action = r->content_type;
+              }
+            else if ( pass == 1 ) /* Try r->handler */
+              {
+               /* This is the second pass... */
+
+               /* Set 'action' search key to 'r->handler' */
+               /* so we search for [php-script]  */
+
+               action = r->handler;
+              }
+
+            #ifdef MOD_GZIP_DEBUG1
+            mod_gzip_printf( "%s: ++++++++++ pass            =%d\n",  cn,pass);
+            mod_gzip_printf( "%s: ++++++++++ t               =[%s]\n",cn,t);
+            mod_gzip_printf( "%s: ++++++++++ r->content_type =[%s]\n",cn,r->content_type);
+            mod_gzip_printf( "%s: ++++++++++ r->handler      =[%s]\n",cn,r->handler);
+            mod_gzip_printf( "%s: ++++++++++ action          =[%s]\n",cn,action);
+            mod_gzip_printf( "%s: ++++++++++ r->filename     =[%s]\n",cn,r->filename);
+            mod_gzip_printf( "%s: ++++++++++ r->uri          =[%s]\n",cn,r->uri);
+            mod_gzip_printf( "%s: ++++++++++ Call mod_gzip_isscript()...\n",cn);
+            #endif
+
+            t =
+            mod_gzip_isscript(
+            r,
+            (_table *) mod_actions_conf->action_types,
+            action ? action : ap_default_type(r)
+            );
+
+            #ifdef MOD_GZIP_DEBUG1
+            mod_gzip_printf( "%s: ++++++++++ Back mod_gzip_isscript()...\n",cn);
+            mod_gzip_printf( "%s: ++++++++++ t               =[%s]\n",cn,t);
+            mod_gzip_printf( "%s: ++++++++++ action          =[%s]\n",cn,action);
+            #endif
+
+            if ( t )
+              {
+               /*
+                * If a program name was found then make it r->filename
+                * and r->uri will become the input name for the program
+                */
+
+               r->filename = ap_pstrdup(r->pool,t);
+
+               break;
+              }
+
+           }/* End 'for( pass )' loop */
+
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: ++++++++++ r->filename=[%s]\n",cn,r->filename);
+        mod_gzip_printf( "%s: ++++++++++ r->uri     =[%s]\n",cn,r->uri);
+        #endif
+
+        /* If a handler was found we are DONE... */
+
+        if ( t )
+          {
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: Handler was found...\n",cn);
+           mod_gzip_printf( "%s: Exit > return( OK ) >\n",cn);
+           #endif
+
+           return OK;
+          }
+
+        #ifdef MOD_GZIP_FUTURE_USE
+
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: ++++++++++ METHODS\n",cn);
+        mod_gzip_printf( "%s: ++++++++++ modp->translate_handler = %ld\n",cn,(long)modp->translate_handler);
+        mod_gzip_printf( "%s: ++++++++++ modp->ap_check_user_id  = %ld\n",cn,(long)modp->ap_check_user_id);
+        mod_gzip_printf( "%s: ++++++++++ modp->auth_checker      = %ld\n",cn,(long)modp->auth_checker);
+        mod_gzip_printf( "%s: ++++++++++ modp->access_checker    = %ld\n",cn,(long)modp->access_checker);
+        mod_gzip_printf( "%s: ++++++++++ modp->type_checker      = %ld\n",cn,(long)modp->type_checker);
+        mod_gzip_printf( "%s: ++++++++++ modp->fixer_upper       = %ld\n",cn,(long)modp->fixer_upper);
+        mod_gzip_printf( "%s: ++++++++++ modp->logger            = %ld\n",cn,(long)modp->logger);
+        mod_gzip_printf( "%s: ++++++++++ modp->header_parser     = %ld\n",cn,(long)modp->header_parser);
+        mod_gzip_printf( "%s: .......... CONTENT HANDLERS\n",cn);
+        #endif /* MOD_GZIP_DEBUG1 */
+
+        if ( !modp->handlers )
+          {
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: .......... NO CONTENT HANDLERS!\n",cn);
+           #endif
+          }
+        else /* There are some handlers... */
+          {
+           for ( handp = modp->handlers; handp->content_type; ++handp )
+              {
+               #ifdef MOD_GZIP_DEBUG1
+               mod_gzip_printf( "%s: .......... handp->content_type = [%s]\n",
+               cn,handp->content_type);
+               mod_gzip_printf( "%s: .......... handp->handler      = %ld\n",cn,(long)handp->handler);
+               #endif
+
+              }/* End 'handp' loop */
+
+          }/* End 'else' */
+
+        #endif /* MOD_GZIP_FUTURE_USE */
+
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: No handler was found...\n",cn);
+        mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+        #endif
+
+        return DECLINED;
+
+        }/* 'if ( mod_gzip_strnicmp( (char *) modp->name, "mod_actions.c", 13 ) == 0 )' */
+
+        count++;
+
+       }/* End 'modp' loop... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: No handler found...\n",cn);
+    mod_gzip_printf( "%s: Exit > return( DECLINED ) > ERROR >\n",cn);
+    #endif
+
+    return DECLINED;
+
+}/* End of mod_gzip_run_mod_action() */
+
+
+int mod_gzip_run_mod_alias( request_rec *r )
+{
+    /*
+     * This calls 'translate_alias_redir()' routine in mod_alias.c
+     * which will search/replace keywords in the URI with the correct
+     * 'ScriptAlias' value(s) from the httpd.conf configuration file.
+     *
+     * 'translate_alias_redir()' is the name of routine registered
+     * by mod_alias.c module as the 'translate' hook.
+     */
+
+    module *modp;
+    int count=0;
+    int rc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_run_mod_alias()";
+    #endif
+
+    const handler_rec *handp;
+
+    /* Currently 9 possible 'event' handlers. */
+    /* Actual content handler in a module is 'extra'. */
+    #define MOD_GZIP_NMETHODS 9
+
+    char *save_filename     = 0;
+    char *save_uri          = 0;
+
+    char nothing[256];
+
+    /*
+     * Start...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry...\n",cn);
+    mod_gzip_printf( "%s: *IN: r->uri         =[%s]\n", cn, r->uri );
+    mod_gzip_printf( "%s: *IN: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
+    mod_gzip_printf( "%s: *IN: r->filename    =[%s]\n", cn, r->filename );
+    #endif
+
+    for ( modp = top_module; modp; modp = modp->next )
+       {
+        /* modp->name list will look like this... */
+        /*--------------------*/
+        /* 00 [mod_gzip.c]    */
+        /* 01 [mod_isapi.c]   */
+        /* 02 [mod_setenv.c]  */
+        /* 02 [mod_actions.c] */
+        /*    ............... */
+        /*    ............... */
+        /* 18 [mod_so.c]      */
+        /* 19 [http_core.c]   <- Always bottom of list (last one called) */
+        /*--------------------*/
+
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: count=%4.4d modp = %10.10ld modp->name=[%s]\n",
+        cn,count,(long)modp, modp->name );
+        #endif
+
+        /*
+        There are only 3 modules that normally have
+        'translate' handlers registered...
+
+        mod_alias
+        mod_userdir
+        http_core
+        */
+
+        if ( ( mod_gzip_strnicmp( (char *) modp->name, "mod_alias.c",   11 ) == 0 ) ||
+             ( mod_gzip_strnicmp( (char *) modp->name, "mod_userdir.c", 13 ) == 0 ) ||
+             ( mod_gzip_strnicmp( (char *) modp->name, "http_core.c",   11 ) == 0 ) )
+        {
+
+        /* Module information... */
+
+        #ifdef MOD_GZIP_DEBUG1
+
+        mod_gzip_printf( "%s: ++++++++++ MODULE FOUND!...\n",cn);
+        mod_gzip_printf( "%s: ++++++++++ modp->module_index = %d\n",cn,(int)modp->module_index);
+
+        mod_gzip_printf( "%s: ++++++++++ METHODS\n",cn);
+        mod_gzip_printf( "%s: ++++++++++ modp->translate_handler = %ld\n",cn,(long)modp->translate_handler);
+        mod_gzip_printf( "%s: ++++++++++ modp->ap_check_user_id  = %ld\n",cn,(long)modp->ap_check_user_id);
+        mod_gzip_printf( "%s: ++++++++++ modp->auth_checker      = %ld\n",cn,(long)modp->auth_checker);
+        mod_gzip_printf( "%s: ++++++++++ modp->access_checker    = %ld\n",cn,(long)modp->access_checker);
+        mod_gzip_printf( "%s: ++++++++++ modp->type_checker      = %ld\n",cn,(long)modp->type_checker);
+        mod_gzip_printf( "%s: ++++++++++ modp->fixer_upper       = %ld\n",cn,(long)modp->fixer_upper);
+        mod_gzip_printf( "%s: ++++++++++ modp->logger            = %ld\n",cn,(long)modp->logger);
+        mod_gzip_printf( "%s: ++++++++++ modp->header_parser     = %ld\n",cn,(long)modp->header_parser);
+        mod_gzip_printf( "%s: .......... CONTENT HANDLERS\n",cn);
+
+        #endif /* MOD_GZIP_DEBUG1 */
+
+        if ( !modp->handlers )
+          {
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: .......... NO CONTENT HANDLERS!\n",cn);
+           #endif
+          }
+        else /* There are some handlers... */
+          {
+           for ( handp = modp->handlers; handp->content_type; ++handp )
+              {
+               #ifdef MOD_GZIP_DEBUG1
+               mod_gzip_printf( "%s: .......... handp->content_type = [%s]\n",
+               cn,handp->content_type);
+               mod_gzip_printf( "%s: .......... handp->handler      = %ld\n",cn,(long)handp->handler);
+               #endif
+
+              }/* End 'handp' loop */
+
+          }/* End 'else' */
+
+        if ( modp->translate_handler )
+          {
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: modp->translate_handler is VALID...\n",cn);
+           #endif
+
+           /*
+           There are only 3 modules that normally have
+           'translate' handlers registered...
+
+           mod_alias     <- Will translate /php3/xxx to c:/php3017/xx
+           mod_userdir
+           http_core
+           */
+
+           /*
+            * This calls 'translate_alias_redir()' routine in mod_alias.c
+            * which will search/replace keywords in the URI with the correct
+            * 'ScriptAlias' value(s) from the httpd.conf configuration file.
+            *
+            * 'translate_alias_redir()' is the name of routine registered
+            * by mod_alias.c module as the 'translate' hook.
+            *
+            * The 'translate_alias_redir()' function in mod_alias.c
+            * is really simple. All it does is check to make sure
+            * that r->uri has some value and, if it does, it calls
+            * another routine in mod_alias.c named 'try_alias_list()'
+            * which replaces any 'ScriptAlias' phrases with their
+            * real values and copies the result to r->filename.
+            *
+            * We must make sure the phrase we want translated is
+            * in r->uri and check for results in r->filename.
+            */
+
+           /*
+            * Calling mod_alias.c translate handler will correctly
+            * translate 'ScriptAlias' phrases such as...
+            *
+            * URI value...
+            * /php3/php3.exe
+            * becomes...
+            * c:/php3017/php3.exe
+            */
+
+           save_filename     = r->filename;
+           save_uri          = r->uri;
+           nothing[0]        = 0;
+
+           r->filename       = nothing;
+           r->uri            = save_filename; /* Phrase to translate */
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: r->filename     = [%s]\n",cn,r->filename);
+           mod_gzip_printf( "%s: r->uri          = [%s]\n",cn,r->uri);
+           mod_gzip_printf( "%s: Call (modp->translate_handler)(r)...\n",cn);
+           #endif
+
+           /* Call the actual translate routine in mod_action module... */
+
+           rc = (modp->translate_handler)( (request_rec *) r );
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: Back (modp->translate_handler)(r)...\n",cn);
+           mod_gzip_printf( "%s: r->filename     = [%s]\n",cn,r->filename);
+           mod_gzip_printf( "%s: r->uri          = [%s]\n",cn,r->uri);
+           #endif
+
+           /*
+            * If there was a successful translation then the return
+            * code will be OK and the translated URI will be sitting
+            * in r->filename. If there were no phrase replacements
+            * then the return code will be DECLINED.
+            */
+
+           #ifdef MOD_GZIP_DEBUG1
+
+           if ( rc == OK )
+             {
+              mod_gzip_printf( "%s: rc = %d = OK\n",cn, rc );
+             }
+           else if ( rc == DECLINED )
+             {
+              mod_gzip_printf( "%s: rc = %d = DECLINED\n",cn, rc );
+             }
+           else if ( rc == DONE ) /* -2 means 'totally done' */
+             {
+              mod_gzip_printf( "%s: rc = %d = DONE\n",cn, rc );
+             }
+           else /* Probably an HTTP ERROR value... */
+             {
+              mod_gzip_printf( "%s: rc = %d = HTTP_ERROR?\n",cn, rc );
+             }
+
+           #endif /* MOD_GZIP_DEBUG */
+
+           /*
+            * Evaluate the results...
+            */
+
+           if ( rc == OK ) /* There was a phrase translation... */
+             {
+              #ifdef MOD_GZIP_DEBUG1
+              mod_gzip_printf( "%s: There was a phrase translation...\n",cn );
+              mod_gzip_printf( "%s: Keeping new 'r->filename'\n",cn );
+              #endif
+
+              /* Do NOT restore 'r->filename' to original value... */
+              /* Just fall-through and continue... */
+             }
+           else /* No phrases were replaced... */
+             {
+              #ifdef MOD_GZIP_DEBUG1
+              mod_gzip_printf( "%s: There were NO phrases translated...\n",cn );
+              mod_gzip_printf( "%s: Restoring 'r->filename' to original value...\n",cn );
+              #endif
+
+              /* Restore 'r->filename' to original value... */
+
+              r->filename = save_filename;
+             }
+
+           /* Always 'restore' URI to original value... */
+
+           r->uri = save_uri;
+
+           /* Turn and burn... */
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: Exit > return( rc=%d ) >\n",cn,rc);
+           #endif
+
+           return rc;
+          }
+        else /* modp->translate_handler is NULL... */
+          {
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: modp->translate_handler is NOT VALID.\n",cn);
+           #endif
+          }
+
+        }/* 'if ( mod_gzip_strnicmp( (char *) modp->name, "mod_actions.c", 13 ) == 0 )' */
+
+        count++;
+
+       }/* End 'modp' loop... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: No handler found...\n",cn);
+    mod_gzip_printf( "%s: Exit > return( DECLINED ) > ERROR >\n",cn);
+    #endif
+
+    return DECLINED;
+
+}/* End of mod_gzip_run_mod_alias() */
+
+
+static int mod_gzip_handler( request_rec *r )
+{
+    /*
+     * The primary module request handler...
+     */
+
+    int  rc=0;
+    char cn[]="mod_gzip_handler()";
+    int access_status=0;
+    int access_status2=0;
+
+    /*
+     * Start...
+     */
+
+    if ( r->server->loglevel == APLOG_DEBUG )
+      {
+       /*
+        * If the user has 'LogLevel debug' set in httpd.conf then
+        * it's ok to go ahead and strike some diagnostic information
+        * to the Apache log(s).
+        *
+        * APLOG_MARK is what supplies __FILE__ and __LINE__ info and
+        * it is actually defined in HTTP_LOG.H as...
+        *
+        * define APLOG_MARK  __FILE__,__LINE__
+        *
+        * Sometimes the original __FILE__ name is very long and is
+        * fairly useless information cluttering up the logs when
+        * there is only 1 possible source file name so
+        * to NOT use it just supply 2 dummy parameters instead.
+        *
+        * The first parameter can be a custom message instead of
+        * the __FILE__ string that would normally be substituted.
+        */
+
+        ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+        "%s: Entry point...",cn);
+
+        ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+        "%s: r->the_request  = [%s]",cn,r->the_request);
+
+        ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+        "%s: r->protocol     = [%s]",cn,r->protocol);
+
+        ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+        "%s: r->proto_num    = %d",cn,(int)r->proto_num);
+
+        ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+        "%s: r->filename     = [%s]",cn,r->filename);
+
+        ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+        "%s: r->uri          = [%s]",cn,r->uri);
+
+        ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+        "%s: r->content_type = [%s]",cn,r->content_type);
+
+        ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+        "%s: r->handler      = [%s]",cn,r->handler);
+
+       }/* End 'if( r->server->loglevel == APLOG_DEBUG )' */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "\n" );
+    mod_gzip_printf( "%s: ```` Entry...\n",cn);
+    mod_gzip_printf( "%s: -------------------------------------------------------------\n",cn);
+    mod_gzip_printf( "%s: *IN: r->uri                 =[%s]\n", cn, r->uri );
+    mod_gzip_printf( "%s: *IN: r->unparsed_uri        =[%s]\n", cn, r->unparsed_uri );
+    mod_gzip_printf( "%s: *IN: r->filename            =[%s]\n", cn, r->filename );
+    mod_gzip_printf( "%s: *IN: r->path_info           =[%s]\n", cn, r->path_info );
+    mod_gzip_printf( "%s: *IN: r->args                =[%s]\n", cn, r->args );
+    mod_gzip_printf( "%s: *IN: r->header_only         =[%s]\n", cn, r->header_only );
+    mod_gzip_printf( "%s: *IN: r->protocol            =[%s]\n", cn, r->protocol );
+    mod_gzip_printf( "%s: *IN: r->proto_num           =%d\n",   cn, r->proto_num );
+    mod_gzip_printf( "%s: *IN: r->hostname            =[%s]\n", cn, r->hostname );
+    mod_gzip_printf( "%s: *IN: r->the_request         =[%s]\n", cn, r->the_request );
+    mod_gzip_printf( "%s: *IN: r->assbackwards        =%d\n",   cn, r->assbackwards );
+    mod_gzip_printf( "%s: *IN: r->status_line         =[%s]\n", cn, r->status_line );
+    mod_gzip_printf( "%s: *IN: r->status              =%d\n",   cn, r->status );
+    mod_gzip_printf( "%s: *IN: r->method              =[%s]\n", cn, r->method );
+    mod_gzip_printf( "%s: *IN: r->method_number       =%d\n",   cn, r->method_number );
+    mod_gzip_printf( "%s: *IN: r->content_type        =[%s]\n", cn, r->content_type );
+    mod_gzip_printf( "%s: *IN: r->handler             =[%s]\n", cn, r->handler );
+    mod_gzip_printf( "%s: *IN: r->content_encoding    =[%s]\n", cn, r->content_encoding );
+    mod_gzip_printf( "%s: *IN: r->content_language    =[%s]\n", cn, r->content_language );
+    mod_gzip_printf( "%s: -------------------------------------------------------------\n",cn);
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.scheme   =[%s]\n", cn, r->parsed_uri.scheme );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.hostinfo =[%s]\n", cn, r->parsed_uri.hostinfo );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.user     =[%s]\n", cn, r->parsed_uri.user );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.password =[%s]\n", cn, r->parsed_uri.password );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.hostname =[%s]\n", cn, r->parsed_uri.hostname );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.port_str =[%s]\n", cn, r->parsed_uri.port_str );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.port     =%u\n",   cn, r->parsed_uri.port );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.path     =[%s]\n", cn, r->parsed_uri.path );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.query    =[%s]\n", cn, r->parsed_uri.query );
+    mod_gzip_printf( "%s: *IN: r->parsed_uri.fragment =[%s]\n", cn, r->parsed_uri.fragment );
+    mod_gzip_printf( "%s: -------------------------------------------------------------\n",cn);
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    /*
+     * Call the real transaction handler....
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Call mod_gzip_request_handler()...\n", cn );
+    #endif
+
+    rc = mod_gzip_request_handler( (request_rec *) r );
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Back mod_gzip_request_handler()... rc=%d\n",cn,rc);
+    #endif
+
+    if ( r->server->loglevel == APLOG_DEBUG )
+      {
+       /*
+        * If LogLevel is 'debug' then show the final return code
+        * value in the log(s)...
+        */
+
+       if ( rc == OK )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "%s: Exit: return( rc = %d = OK )", cn, rc );
+         }
+       else if ( rc == DECLINED )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "%s: Exit: return( rc = %d = DECLINED )", cn, rc );
+         }
+       else /* It's probably an HTTP error code... */
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "%s: Exit: return( rc = %d = HTTP ERROR CODE? )", cn, rc );
+         }
+
+      }/* End 'if( r->server->loglevel == APLOG_DEBUG )' */
+
+    #ifdef MOD_GZIP_DEBUG1
+
+    if ( rc == OK )
+      {
+       mod_gzip_printf( "%s: rc = %d OK\n", cn, (int) rc);
+      }
+    else if ( rc == DECLINED )
+      {
+       mod_gzip_printf( "%s: rc = %d DECLINED\n", cn, (int) rc );
+      }
+    else /* It's probably an HTTP error code... */
+      {
+       mod_gzip_printf( "%s: rc = %d ( HTTP ERROR CODE? )\n", cn, (int) rc );
+      }
+
+    mod_gzip_printf( "%s: Exit > return( rc = %d ) >\n",cn,rc );
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    return rc;
+
+}/* End of mod_gzip_handler() */
+
+typedef struct {
+    table *action_types;       /* Added with Action... */
+    char *scripted[METHODS];   /* Added with Script... */
+    array_header *xmethods;    /* Added with Script -- extension methods */
+} action_dir_config2;
+
+extern module action_module;
+
+int mod_gzip_request_handler( request_rec *r )
+{
+    /*
+     * Process a new request...
+     */
+
+    int             rc                = 0;
+    int             loglevel          = 0;
+    int             do_command        = 0;
+    int             process           = 0;
+    int             action_flag       = 0;
+    long            compression_ratio = 0;
+
+    const char*     has_encoding      = 0;
+    const char*     accept_encoding   = 0;
+
+    #ifdef MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
+    char tmp[4096]; /* Scratch buffer for HTML output */
+    #endif
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_request_handler()";
+    const char* the_type = 0;
+    #endif
+
+    #ifdef MOD_GZIP_USES_APACHE_LOGS
+    char log_info[40]; /* Scratch buffer */
+    #endif
+
+    void *modconf = r->server->module_config;
+
+    mod_gzip_conf *conf = 0; /* Pointer to our own config data */
+
+    /*
+     * Start...
+     *
+     * Establish a local pointer to module configuration data...
+     */
+
+    conf = (mod_gzip_conf *)
+    ap_get_module_config(modconf, &gzip_module);
+
+    /*
+     * Get the current Apache log level...
+     */
+
+    loglevel = r->server->loglevel;
+
+    #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+    /*
+     * If the MOD_GZIP_USES_APACHE_LOGS compile-time switch is ON
+     * then the Apache log module interface code is being included.
+     *
+     * Reset the module 'notes' that are used by mod_gzip to
+     * add entries to Apache standard log files...
+     *
+     * See the note farther below about how to add mod_gzip
+     * compression information to any standard Apache log file.
+     */
+
+    /* Default for 'mod_result' message is 'DECLINED:NOP'... */
+
+    ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NOP"));
+
+    /* Default for in/out size is 'n/a'... 'Not available'...*/
+
+    sprintf( log_info, "n/a" );
+
+    ap_table_setn( r->notes,"mod_gzip_input_size",ap_pstrdup(r->pool,log_info));
+    ap_table_setn( r->notes,"mod_gzip_output_size",ap_pstrdup(r->pool,log_info));
+
+    /* Default for compression ratio is '0' percent... */
+
+    ap_table_setn( r->notes,"mod_gzip_compression_ratio",ap_pstrdup(r->pool,"0"));
+
+    #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+    #ifdef MOD_GZIP_DEBUG1
+
+    /* Request info... */
+
+    mod_gzip_printf( "%s: Entry...\n",cn);
+    mod_gzip_printf( "%s: mod_gzip_version    =[%s]\n", cn, mod_gzip_version);
+    mod_gzip_printf( "%s: conf->req           = %d\n",  cn, (int) conf->req);
+    mod_gzip_printf( "%s: conf->cache.root    =[%s]\n", cn, conf->cache.root);
+    mod_gzip_printf( "%s: *IN: r->uri         =[%s]\n", cn, r->uri);
+    mod_gzip_printf( "%s: *IN: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri);
+    mod_gzip_printf( "%s: *IN: r->filename    =[%s]\n", cn, r->filename);
+    mod_gzip_printf( "%s: *IN: r->handler     =[%s]\n", cn, r->handler);
+    mod_gzip_printf( "%s: r->finfo.st_size    = %ld\n", cn, (long) r->finfo.st_size);
+
+    /* NOTE: The r->headers_out content type value has not normally */
+    /* been set at this point but grab a pointer to it and show */
+    /* it just to make sure. The r->content_type value, however, */
+    /* normally WILL have some value at this point. */
+
+    the_type = ap_table_get( r->headers_out,"Content-type" );
+
+    mod_gzip_printf( "%s: r->headers_out, Content-type = [%s]\n",cn,the_type);
+    mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type );
+
+    /* The r->handler ASCII name string is the all-important */
+    /* jump table name for the module that will handle the */
+    /* transaction. If this is a CGI jump then it will normally */
+    /* have a value of 'cgi-script' at this point. */
+
+    mod_gzip_printf( "%s: r->handler      = [%s]\n",cn,r->handler );
+
+    /* Server info... */
+
+    mod_gzip_printf( "%s: r->server->path            = [%s]\n",cn,r->server->path );
+    mod_gzip_printf( "%s: r->server->pathlen         = %d\n",  cn,r->server->pathlen);
+    mod_gzip_printf( "%s: r->server->server_admin    = [%s]\n",cn,r->server->server_admin);
+    mod_gzip_printf( "%s: r->server->server_hostname = [%s]\n",cn,r->server->server_hostname);
+    mod_gzip_printf( "%s: r->server->error_fname     = [%s]\n",cn,r->server->error_fname);
+
+    /* Environment info... */
+
+    mod_gzip_printf( "%s: DOCUMENT_ROOT = [%s]\n",cn,ap_document_root(r));
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    /*
+     * Check the 'master' request control switch and see if mod_gzip
+     * is ON (ENABLED) or OFF (DISABLED)...
+     */
+
+    if ( conf->req != 1 )
+      {
+       /* mod_gzip is currently DISABLED so DECLINE the processing... */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: conf->req = %d = OFF\n",cn,conf->req);
+       mod_gzip_printf( "%s: The module is currently DISABLED\n",cn);
+       mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+       #endif
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:DISABLED"));
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       return DECLINED;
+
+      }/* End 'if( conf->req != 1 )' */
+
+    /*
+     * Check for a default HTTP support level ( if used ).
+     * If no value for conf->min_http was supplied in the
+     * httpd.conf file then the default value will be 0
+     * so that ALL levels of HTTP will be OK...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: *HTTP CHECK:conf->min_http = %d\n",   cn, conf->min_http );
+    mod_gzip_printf( "%s: *HTTP CHECK:r->proto_num   = %d\n",   cn, r->proto_num );
+    mod_gzip_printf( "%s: *HTTP CHECK:r->protocol    = [%s]\n", cn, r->protocol );
+    #endif
+
+    if ( r->proto_num < conf->min_http )
+      {
+       /* The HTTPx/x version number does not meet the minimum requirement */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Request HTTP level does not meet minimum requirement\n",cn);
+       mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+       #endif
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       sprintf( log_info, "DECLINED:%s:%d", r->protocol, r->proto_num );
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,log_info));
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       return DECLINED;
+
+      }/* End 'if ( r->proto_num < conf->min_http )' */
+
+    else /* Protocol level is OK... */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Request HTTP level is OK...\n",cn);
+       #endif
+      }
+
+    #ifdef MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
+
+    /*
+     * Internal command pickups...
+     *
+     * If this module was compiled with the
+     * MOD_GZIP_ALLOWS_INTERNAL_COMMANDS switch ON
+     * then the first thing we do is check for valid
+     * URL-based internal commands.
+     *
+     * Rather than check for all possible commands each time
+     * just do 1 quick check for the command prefix and set
+     * a flag to indicate if there is any need to enter the
+     * actual command handler...
+     */
+
+    if ( strstr( r->filename, "mod_gzip_command_" ) )
+      {
+       do_command = 1; /* Process the command */
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: do_command = %d\n",cn,do_command);
+    #endif
+
+    if ( do_command )
+      {
+       /* Determine the exact command and respond... */
+
+       if ( strstr( r->filename, "mod_gzip_command_version" ) )
+         {
+          /*------------------------------------------------------*/
+          /* Command: 'mod_gzip_command_version'                  */
+          /* Purpose: Return the current mod_gzip version number. */
+          /* Comment: Allows anyone to query any Apache Server at */
+          /*          any URL with a browser and discover if      */
+          /*          mod_gzip is in use at that site.            */
+          /*------------------------------------------------------*/
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: 'mod_gzip_command_version' seen...\n",cn);
+          #endif
+
+          /* NOTE: mod_gzip command results are not sent compressed */
+
+          /* Build the response buffer... */
+
+          sprintf( tmp,
+          "<html><body><pre>"
+          "mod_gzip is available on this Server\r\n"
+          "mod_gzip version = %s\r\n"
+          "</pre></body></html>",
+          mod_gzip_version
+          );
+
+          /* For all mod_gzip commands that are intercepted we */
+          /* simply return OK. */
+
+          return( mod_gzip_send_html_command_response( r, tmp, "text/html" ));
+         }
+       else if ( strstr( r->filename, "mod_gzip_command_showstats" ) )
+         {
+          /*------------------------------------------------------*/
+          /* Command: 'mod_gzip_command_showstats'                */
+          /* Purpose: Display compression statistics.             */
+          /* Comment: Allows anyone to query any Apache Server at */
+          /*          any URL with a browser and get a report     */
+          /*          about compression results.                  */
+          /*------------------------------------------------------*/
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: 'mod_gzip_command_showstats' seen...\n",cn);
+          #endif
+
+          /* NOTE: mod_gzip command results are not sent compressed */
+
+          /* Build the response buffer... */
+
+          /* NOTE: This command has been temporarily removed */
+
+          sprintf( tmp,
+          "<html><body><pre>"
+          "mod_gzip is available on this Server\r\n"
+          "mod_gzip version = %s\r\n\r\n"
+          "The 'mod_gzip_command_showstats' command has been temporarily removed.\r\n"
+          "</pre></body></html>",
+          mod_gzip_version
+          );
+
+          /* For all mod_gzip commands that are intercepted we */
+          /* simply return OK. */
+
+          return( mod_gzip_send_html_command_response( r, tmp, "text/html" ));
+         }
+       else if ( strstr( r->filename, "mod_gzip_command_resetstats" ) )
+         {
+          /*------------------------------------------------------*/
+          /* Command: 'mod_gzip_command_resetstats'               */
+          /* Purpose: Resets the compression statistics.          */
+          /* Comment: Allows the compression statistics to be     */
+          /*          reset using only a browser.                 */
+          /*------------------------------------------------------*/
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: 'mod_gzip_command_resetstats' seen...\n",cn);
+          #endif
+
+          /* NOTE: mod_gzip command results are not sent compressed */
+
+          /* Build the response buffer... */
+
+          /* NOTE: This command has been temporarily removed */
+
+          sprintf( tmp,
+          "<html><body><pre>"
+          "mod_gzip is available on this Server\r\n"
+          "mod_gzip version = %s\r\n\r\n"
+          "The 'mod_gzip_command_resetstats' command has been temporarily removed.\r\n"
+          "</pre></body></html>",
+          mod_gzip_version
+          );
+
+          /* For all mod_gzip commands that are intercepted we */
+          /* simply return OK. */
+
+          return( mod_gzip_send_html_command_response( r, tmp, "text/html" ));
+         }
+       else /* Unrecognized command... */
+         {
+          /* The command prefix was 'seen' and the 'do_command' flag */
+          /* was TRUE but either the command was mis-typed or there */
+          /* is no such command available. This is not an ERROR and */
+          /* we should simply fall-through and assume that the URL */
+          /* is valid for the local Server. A 404 will be returned */
+          /* if there is no object that actually matches the name. */
+         }
+
+      }/* End 'if( do_command )' */
+
+    #endif /* MOD_GZIP_ALLOWS_INTERNAL_COMMANDS */
+
+    /*
+     * Sanity checks...
+     */
+
+    /*
+     * If the requested file already contains the .gz designation
+     * then we must assume it is pre-compressed and let the
+     * default logic take care of sending the file. This module
+     * doesn't really care if a .gz file was actually requested
+     * or if it is the source target because of a successful
+     * Server side 'negotiation'. Doesn't matter.
+     */
+
+    if ( ( r->filename ) && ( strstr( r->filename, ".gz" ) ) )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: r->filename already contains '.gz'.\n",cn);
+       mod_gzip_printf( "%s: Pre-compression is assumed.\n",cn);
+       mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+       #endif
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:HAS.GZ"));
+
+       if ( r->server->loglevel == APLOG_DEBUG )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "mod_gzip: Files with .gz file extension are skipped.");
+         }
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       return DECLINED;
+      }
+    else /* r->filename doesn not contain '.gz' designator... */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: r->filename does NOT contain '.gz'.\n",cn);
+       mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
+       #endif
+      }
+
+    /*
+     * For now just block all attempts to compress 'image/*' MIME
+     * type even if user is trying to do so. Too many issues with
+     * broken browsers when it comes to decoding compressed images.
+     *
+     * WARNING: Don't submit r->content_type to strstr() it if is
+     * NULL or the API call will GP fault. Go figure.
+     */
+
+    if ( ( r->content_type ) && ( strstr( r->content_type, "image/" ) ) )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: r->content_type contains 'image/'.\n",cn);
+       mod_gzip_printf( "%s: Image compression is temporaily BLOCKED\n",cn);
+       mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+       #endif
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:IMAGE"));
+
+       if ( r->server->loglevel == APLOG_DEBUG )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "mod_gzip: Graphics image compression option is temporarily disabled.");
+         }
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       return DECLINED;
+      }
+
+    /*
+     * Safeguard against situations where some other module or
+     * filter has gotten to this request BEFORE us and has already
+     * added the 'Content-encoding: gzip' field to the output header.
+     * It must be assumed that whoever added the header prior to this
+     * point also took care of the compression itself.
+     *
+     * If the output header already contains "Content-encoding: gzip"
+     * then simply DECLINE the processing and let the default chain
+     * take care of it...
+     */
+
+    has_encoding = ap_table_get( r->headers_out, "Content-encoding" );
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: has_encoding = [%s]\n",cn,has_encoding);
+    #endif
+
+    if ( has_encoding ) /* 'Content-encoding' field is present... */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Output header already contains 'Content-encoding:' field\n",cn);
+       mod_gzip_printf( "%s: Checking for 'gzip' designator...\n",cn);
+       #endif
+
+       if ( strstr( has_encoding, "gzip" ) ||
+                       strstr( has_encoding, "deflate" ) )
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: 'Content-encoding:' field contains 'gzip' or 'deflate' designator...\n",cn);
+          mod_gzip_printf( "%s: Pre-compression is assumed.\n",cn);
+          mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+          #endif
+
+          #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+          /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+          ap_table_setn(
+          r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:HAS_CE:GZIP"));
+
+          if ( r->server->loglevel == APLOG_DEBUG )
+            {
+             ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+             "mod_gzip: Header already has 'Content-encoding: gzip'");
+            }
+
+          #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+          return DECLINED;
+         }
+       else /* 'gzip' designator not found... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: 'Content-encoding:' field does NOT contain 'gzip' or 'deflate' designator...\n",cn);
+          mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
+          #endif
+         }
+
+      }/* End 'if( has_encoding )' */
+
+    else /* Output header does NOT contain 'Content-encoding:' field... */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Output header does NOT contain 'Content-encoding:' field.\n",cn);
+       mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
+       #endif
+      }
+
+    /*
+     * Basic sanity checks completed and we are still here.
+     *
+     * Now we must determine if the User-Agent is capable of receiving
+     * compressed data...
+     *
+     * There are, currently, many reasons why it is actually never
+     * enough to simply trust the 'Accept-encoding: foo, bar'
+     * request header field when it comes to actually determining
+     * if a User-agent is capable of receiving content or transfer
+     * encodings.
+     *
+     * Some of them are...
+     *
+     * 1. There have been several major releases of popular browsers
+     *    that actually send the 'Accept-encoding:' request field but
+     *    are, in reality, unable to perform the specified decoding(s).
+     *    In some cases the result will be that the browser screen
+     *    simply fills with garbage ( the binary compressed data
+     *    itself ) but in some cases the browser will actually crash.
+     *
+     * 2. There have been other major releases of browsers that are
+     *    specifying multiple 'Accept-encoding' techniques with no
+     *    'Q' values whatsoever and they are actually only able to
+     *    handle one of the multiple types specified. There is no
+     *    way to know which type is 'real' other than by using other
+     *    empiricial data extracted from the 'User-agent' field
+     *    or other inbound request headers.
+     *
+     * 3. Same as 1 and 2 but relates to SIZE. Some major browser
+     *    releases can handle the encoded content but only up to
+     *    a certain 'SIZE' limit and then they will fail. There
+     *    is no way for a User-agent to specify this limitation
+     *    via HTTP so empirical header analysis is the only option.
+     *
+     * 4. The HTTP specification has no way for a Server to distinguish
+     *    from the 'Accept encoding: foo, bar' input request field
+     *    whether the user agent can only support the specified encodings
+     *    as either a Content-encoding OR a Transfer-encoding, but
+     *    not both. There is also no way of knowing if the user
+     *    agent is able to handle any of the specified types being
+     *    used as both a Content-encoding AND a Transfer-encoding
+     *    for the same message body. All the Server can do is assume
+     *    that the encodings are valid in any/all combinations
+     *    and that the user agent can 'Accept' them as either
+     *    'Content' encodings and/or 'Transfer' encodings under
+     *    any and all circumstances. This blanket assumption will
+     *    cause problems with some release versions of some browsers
+     *    because the assumed 'do all' capability is simply not a
+     *    reality.
+     *
+     * 5. Many browsers ( such as Netscape 4.75 for UNIX ) are unable
+     *    to handle Content-encoding only for specific kinds of HTML
+     *    transactions such as Style Sheets even though the browser
+     *    says it is HTTP 1.1 compliant and is suppying the standard
+     *    'Accept-encoding: gzip' field. According to the IETF
+     *    specifications any user-agent that says it can accept
+     *    encodings should be able to do so for all types of HTML
+     *    transactions but this is simply not the current reality.
+     *    Some will, some won't... even if they say they can.
+     *
+     * This version of this module takes the 'What, me worry' approach
+     * and simply uses the accepted method of relying solely on the
+     * 'Accept-encoding: foo, bar' field and also assumes this means
+     * that the User-agent can accept the specified encodings as
+     * either Content-encodings (CE) and/or Transfer-encodings (TE)
+     * under all circumstances and in any combinations that the
+     * Server decides to send.
+     *
+     * It also assumes that the caller has no preference and should
+     * be able to decode any of the specified encodings equally well.
+     * Most user-agents sending the 'Accept-encoding:' field do NOT
+     * supply any 'Q' values to help with determining preferences.
+     */
+
+    accept_encoding = ap_table_get( r->headers_in, "Accept-Encoding" );
+
+    #ifdef MOD_GZIP_DEBUG1
+
+    if ( accept_encoding )
+      {
+       mod_gzip_printf( "%s: 'Accept Encoding:' field seen.\n",cn);
+      }
+    else
+      {
+       mod_gzip_printf( "%s: 'Accept Encoding' field NOT seen.\n",cn);
+      }
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    /* If Accept-Encoding is applicable to this request...*/
+
+    if ( accept_encoding )
+      {
+       /* ...and if it has the right 'gzip' indicator... */
+          /* We record the compression format in a request note, so we
+        * can get it again later, and so it can potentially be logged.
+        */
+       if ( strstr( accept_encoding, "gzip" ) )
+         {
+          process = 1; /* ...set the 'process' flag TRUE */
+          ap_table_setn( r->notes,"mod_gzip_compression_format",
+                                                ap_pstrdup(r->pool,"gzip"));
+
+         }
+       else if ( strstr( accept_encoding, "deflate" ) )
+         {
+          process = 1; /* ...set the 'process' flag TRUE */
+          ap_table_setn( r->notes,"mod_gzip_compression_format",
+                                                ap_pstrdup(r->pool,"deflate"));
+         }
+
+      }/* End 'if( accept_encoding )' */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: 'process' flag = %d\n",cn,process);
+    #endif
+
+    if ( !process ) /* Request does not meet criteria for processing... */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: No 'gzip' capability specified by user-agent.\n",cn);
+       mod_gzip_printf( "%s: 'process' flag is FALSE.\n",cn);
+       mod_gzip_printf( "%s: This request will not be processed.\n",cn);
+       mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+       #endif
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_GZIP"));
+
+       if ( r->server->loglevel == APLOG_DEBUG )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "mod_gzip: The inbound request header does not have 'Accept-encoding: gzip'");
+         }
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       return DECLINED;
+      }
+    else /* 'gzip' designator was seen in 'Accept-Encoding:' field */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: 'gzip' or 'deflate' capability specified by user-agent.\n",cn);
+       mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
+       #endif
+      }
+
+    /*
+     * Handle the transaction...
+     *
+     * At this point the inbound header analysis has been completed
+     * and we are assuming that the user agent is capable of accepting
+     * the content encodings we can provide.
+     *
+     * We must now 'do the right thing' based on what type of
+     * request it actually is...
+     */
+
+     #ifdef MOD_GZIP_DEBUG1
+     mod_gzip_printf( "%s: r->handler      = [%s]\n",cn,r->handler);
+     mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
+     mod_gzip_printf( "%s: Call mod_gzip_get_action_flag()...\n",cn);
+     #endif
+
+     action_flag =
+     mod_gzip_get_action_flag(
+     (request_rec   *) r,
+     (mod_gzip_conf *) conf
+     );
+
+     #ifdef MOD_GZIP_DEBUG1
+     mod_gzip_printf( "%s: Back mod_gzip_get_action_flag()...\n",cn);
+     mod_gzip_printf( "%s: action_flag           = %d\n",cn,action_flag);
+     mod_gzip_printf( "%s: conf->do_static_files = %d\n",cn,(int)conf->do_static_files);
+     mod_gzip_printf( "%s: conf->do_cgi          = %d\n",cn,(int)conf->do_cgi);
+     #endif
+
+     /*
+      * Perform the right 'action' for this transaction...
+      */
+
+     if ( action_flag == MOD_GZIP_IMAP_DECLINED1 )
+       {
+        /*
+         * If the transaction is to be DECLINED then just set the final
+         * return code to DECLINED, fall through, and return.
+         */
+
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: action_flag = MOD_GZIP_IMAP_DECLINED1\n",cn);
+        #endif
+
+        if ( r->server->loglevel == APLOG_DEBUG )
+          {
+           ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_gzip: action_flag = MOD_GZIP_IMAP_DECLINED1 ");
+          }
+
+        rc = DECLINED;
+       }
+     else if ( action_flag == MOD_GZIP_IMAP_DYNAMIC1 )
+       {
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: action_flag = MOD_GZIP_IMAP_DYNAMIC1\n",cn);
+        #endif
+
+        if ( r->server->loglevel == APLOG_DEBUG )
+          {
+           ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_gzip: action_flag = MOD_GZIP_IMAP_DYNAMIC1 ");
+          }
+
+        /*
+         * Check the flag that can control whether or not the
+         * CGI dynamic output handler is ever called...
+         */
+
+        if ( conf->do_cgi != 1 ) /* CGI handler is OFF for now... */
+          {
+           if ( r->server->loglevel == APLOG_DEBUG )
+             {
+              ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+              "mod_gzip: Calls to CGI handler currently DISABLED ");
+             }
+
+           #ifdef MOD_GZIP_USES_APACHE_LOGS
+           /* Update the result string for Apache log(s)... */
+           ap_table_setn(
+           r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:CGI_OFF"));
+           #endif
+
+           rc = DECLINED; /* Just set final return code and fall through */
+
+          }/* End 'if( conf->do_cgi == 0 )' */
+
+        else /* It's OK to call the handler... */
+          {
+           if ( r->server->loglevel == APLOG_DEBUG )
+             {
+              ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+              "mod_gzip: Calling cgi_handler for r->uri=[%s]",r->uri);
+             }
+
+           /* Take care of some business BEFORE calling the */
+           /* dynamic handler... */
+
+           mod_gzip_prepare_for_dynamic_call( r );
+
+           /* PHP NOTE */
+           /* r->path_info must be set before ap_add_cgi_vars() */
+           /* is called from within the upcoming hander or we */
+           /* won't get PATH_INFO or PATH_TRANSLATED environment */
+           /* variables set and PHP.EXE will return 'No input file' */
+           /* error message since it depends on both of these being */
+           /* set. r->path_info must be set to r->uri */
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: 1 r->uri       = [%s]\n", cn, r->uri );
+           mod_gzip_printf( "%s: 1 r->path_info = [%s]\n", cn, r->path_info );
+           mod_gzip_printf( "%s: Setting r->path_info to r->uri for CGI...\n", cn );
+           #endif
+
+           r->path_info = r->uri;
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: 2 r->uri       = [%s]\n", cn, r->uri );
+           mod_gzip_printf( "%s: 2 r->path_info = [%s]\n", cn, r->path_info );
+           #endif
+
+           /* Call the actual handler... */
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: Call mod_gzip_cgi_handler()...\n",cn);
+           #endif
+
+           rc = mod_gzip_cgi_handler( (request_rec *) r );
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: Back mod_gzip_cgi_handler()... rc=%d\n",cn,rc);
+           #endif
+
+          }/* End 'else' - OK to call handler */
+       }
+     else if ( action_flag == MOD_GZIP_IMAP_STATIC1 )
+       {
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: action_flag = MOD_GZIP_IMAP_STATIC1\n",cn);
+        #endif
+
+        if ( r->server->loglevel == APLOG_DEBUG )
+          {
+           ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_gzip: action_flag = MOD_GZIP_IMAP_STATIC1 ");
+          }
+
+        /*
+         * Check the flag that can control whether or not the
+         * static handler is ever called...
+         */
+
+        if ( conf->do_static_files != 1 ) /* Static handler is OFF for now... */
+          {
+           if ( r->server->loglevel == APLOG_DEBUG )
+             {
+              ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+              "mod_gzip: Calls to static handler currently DISABLED ");
+             }
+
+           #ifdef MOD_GZIP_USES_APACHE_LOGS
+           /* Update the result string for Apache log(s)... */
+           ap_table_setn(
+           r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:STATIC_OFF"));
+           #endif
+
+           rc = DECLINED; /* Just set final return code and fall through */
+
+          }/* End 'if( conf->do_static == 0 )' */
+
+        else /* It's OK to call the handler... */
+          {
+           if ( r->server->loglevel == APLOG_DEBUG )
+             {
+              ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+              "mod_gzip: Calling static_handler for r->uri=[%s]",r->uri);
+             }
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: Call mod_gzip_static_file_handler()...\n",cn);
+           #endif
+
+           rc = mod_gzip_static_file_handler( (request_rec *) r );
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: Back mod_gzip_static_file_handler()... rc=%d\n",cn,rc);
+           #endif
+
+          }/* End 'else' - OK to call the handler */
+       }
+     else /* Safety catch... No pickup for the 'action' flag... */
+       {
+        if ( r->server->loglevel == APLOG_DEBUG )
+          {
+           ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_gzip: action_flag = MOD_GZIP_IMAP_????? Unknown value");
+          }
+
+        if ( r->server->loglevel == APLOG_DEBUG )
+          {
+           ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_gzip: No pickup for specified 'action' flag.");
+          }
+
+        #ifdef MOD_GZIP_DEBUG1
+        mod_gzip_printf( "%s: action_flag = MOD_GZIP_??? Unknown value\n",cn);
+        #endif
+
+        rc = DECLINED;
+       }
+
+     /*
+      * Record results to logs, if applicable, and return...
+      *
+      * The 'r->notes' values that can be used to disply result
+      * information in the standard Apache log files should have
+      * already been updated by the handler that was actually
+      * used to process the transaction.
+      */
+
+     #ifdef MOD_GZIP_DEBUG1
+
+     if ( rc == OK )
+       {
+        mod_gzip_printf( "%s: Exit > return( rc=%d OK ) >\n",cn,rc);
+       }
+     else if ( rc == DECLINED )
+       {
+        mod_gzip_printf( "%s: Exit > return( rc=%d DECLINED ) >\n",cn,rc);
+       }
+     else /* HTTP ERROR VALUE... */
+       {
+        mod_gzip_printf( "%s: Exit > return( rc=%d HTTP_ERROR ) >\n",cn,rc);
+       }
+
+     #endif /* MOD_GZIP_DEBUG1 */
+
+     return rc; /* Could be OK or DECLINED or HTTP_ERROR */
+
+}/* End of mod_gzip_request_handler() */
+
+int mod_gzip_prepare_for_dynamic_call( request_rec *r )
+{
+    int rc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_prepare_for_dynamic_call()";
+    #endif
+
+    /*
+     * Start...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry...\n",cn);
+    #endif
+
+    /*
+     * mod_gzip can run other modules directly...
+     */
+
+    /*
+     * First run mod_action and see it there's a SCRIPT
+     * for this mime type...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: 1 ***: r->uri         =[%s]\n", cn, r->uri );
+    mod_gzip_printf( "%s: 1 ***: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
+    mod_gzip_printf( "%s: 1 ***: r->filename    =[%s]\n", cn, r->filename );
+    mod_gzip_printf( "%s: 1 ***: r->content_type=[%s]\n", cn, r->content_type );
+    mod_gzip_printf( "%s: 1 ***: r->handler     =[%s]\n", cn, r->handler );
+    mod_gzip_printf( "%s: Call mod_gzip_run_mod_action(r)...\n",cn);
+    #endif
+
+    rc = mod_gzip_run_mod_action( (request_rec *) r  );
+
+    #ifdef MOD_GZIP_DEBUG1
+
+    mod_gzip_printf( "%s: Back mod_gzip_run_mod_action(r)...\n",cn);
+
+    if ( rc == OK )
+      {
+       mod_gzip_printf( "%s: rc = %d = OK\n",cn, rc );
+      }
+    else if ( rc == DECLINED )
+      {
+       mod_gzip_printf( "%s: rc = %d = DECLINED\n",cn, rc );
+      }
+    else if ( rc == DONE ) /* -2 means 'totally done' */
+      {
+       mod_gzip_printf( "%s: rc = %d = DONE\n",cn, rc );
+      }
+    else /* Probably an HTTP ERROR value... */
+      {
+       mod_gzip_printf( "%s: rc = %d = HTTP_ERROR?\n",cn, rc );
+      }
+
+    mod_gzip_printf( "%s: 2 ***: r->uri         =[%s]\n", cn, r->uri );
+    mod_gzip_printf( "%s: 2 ***: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
+    mod_gzip_printf( "%s: 2 ***: r->filename    =[%s]\n", cn, r->filename );
+    mod_gzip_printf( "%s: 2 ***: r->content_type=[%s]\n", cn, r->content_type );
+    mod_gzip_printf( "%s: 2 ***: r->handler     =[%s]\n", cn, r->handler );
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    /*
+     * Now run mod_alias and get any aliases converted
+     * to real pathnames...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Call mod_gzip_run_mod_alias(r)...\n",cn);
+    #endif
+
+    rc = mod_gzip_run_mod_alias( (request_rec *) r  );
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Back mod_gzip_run_mod_alias(r)...\n",cn);
+
+    if ( rc == OK )
+      {
+       mod_gzip_printf( "%s: rc = %d = OK\n",cn, rc );
+      }
+    else if ( rc == DECLINED )
+      {
+       mod_gzip_printf( "%s: rc = %d = DECLINED\n",cn, rc );
+      }
+    else if ( rc == DONE ) /* -2 means 'totally done' */
+      {
+       mod_gzip_printf( "%s: rc = %d = DONE\n",cn, rc );
+      }
+    else /* Probably an HTTP ERROR value... */
+      {
+       mod_gzip_printf( "%s: rc = %d = HTTP_ERROR?\n",cn, rc );
+      }
+
+    mod_gzip_printf( "%s: 3 ***: r->uri         =[%s]\n", cn, r->uri );
+    mod_gzip_printf( "%s: 3 ***: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
+    mod_gzip_printf( "%s: 3 ***: r->filename    =[%s]\n", cn, r->filename );
+    mod_gzip_printf( "%s: 3 ***: r->content_type=[%s]\n", cn, r->content_type );
+    mod_gzip_printf( "%s: 3 ***: r->handler     =[%s]\n", cn, r->handler );
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    return OK;
+
+}/* End of mod_gzip_prepare_for_dynamic_call() */
+
+
+int mod_gzip_static_file_handler( request_rec *r )
+{
+    int             rc         = 0;
+    long            input_size = 0;
+    FILE*           ifh1       = 0;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_static_file_handler()";
+    #endif
+
+    /*
+     * Start...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Processing file [%s]\n",cn,r->filename);
+    mod_gzip_printf( "%s: r->finfo.st_size = %ld\n",
+               cn, (long) r->finfo.st_size);
+    #endif
+
+    /*
+     * If there is a valid file size already associated with
+     * the request then we can assume the core stat() call succeeded
+     * and that r->filename actually exists. We shouldn't need
+     * to waste a call to 'fopen()' just to find out for ourselves
+     * if the file exists.
+     *
+     * If the inbound file size was '0' then we need to do some
+     * verifications of our own before we give up since the
+     * absence of size might just be a simple bug in the parent code.
+     */
+
+    if ( r->finfo.st_size > 0 )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Source file length already known...\n",cn);
+       #endif
+
+       input_size = (long) r->finfo.st_size;
+      }
+    else /* Do our own checking... */
+      {
+       /*
+        * See if the requested source file exists...
+        * Be SURE to open the file in BINARY mode...
+        */
+
+       ifh1 = fopen( r->filename, "rb" );
+
+       if ( !ifh1 ) /* The file cannot be found or opened... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: The requested source file was NOT FOUND.\n",cn);
+          mod_gzip_printf( "%s: Exit > return( HTTP_NOT_FOUND ) >\n",cn);
+          #endif
+
+          #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+          /* HTTP ERROR conditions provides a short ':WHYTAG' for logs */
+
+          ap_table_setn(
+          r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:HTTP_NOT_FOUND"));
+
+          #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+          return HTTP_NOT_FOUND;
+         }
+       else /* The file was found and opened OK... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: The requested source file is now OPEN...\n",cn);
+          #endif
+         }
+
+       /*
+        * Move the current file pointer to the end of the file...
+        */
+
+       if ( fseek( ifh1, 0, SEEK_END ) )
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: ERROR: fseek() call failed...\n",cn);
+          #endif
+
+          fclose( ifh1 ); /* FILE is still open so CLOSE it... */
+
+          /* fseek() failure could be a platform issue so log the event... */
+
+          ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server,
+          "mod_gzip: fseek() failed for r->filename=[%s]",r->filename );
+
+          /* Return DECLINED and let default logic finish the request... */
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+          #endif
+
+          #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+          /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+          ap_table_setn(
+          r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FSEEK_FAIL"));
+
+          #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+          return DECLINED;
+         }
+
+       /*
+        * Get the current SIZE of the requested file...
+        */
+
+       input_size = (long) ftell( ifh1 );
+
+       if ( input_size == -1l )
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: ERROR: ftell() call failed...\n",cn);
+          #endif
+
+          fclose( ifh1 ); /* FILE is still open so CLOSE it... */
+
+          /* ftell() failure could be a platform issue so log the event... */
+
+          ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server,
+          "mod_gzip: ftell() failed for r->filename=[%s]", r->filename );
+
+          /* Return DECLINED and let default logic finish the request... */
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+          #endif
+
+          #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+          /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+          ap_table_setn(
+          r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FTELL_FAIL"));
+
+          #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+          return DECLINED;
+         }
+
+       /*
+        * Once we have the length just close the file...
+        */
+
+       if ( fclose( ifh1 ) == EOF )
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: ERROR: fclose() following ftell() call failed...\n",cn);
+          #endif
+
+          /* fclose() failure could be a platform issue so log the event... */
+
+          ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server,
+          "mod_gzip: fclose() failed for r->filename=[%s]",r->filename );
+
+          /* Return DECLINED and let default logic finish the request... */
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+          #endif
+
+          #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+          /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+          ap_table_setn(
+          r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FCLOSE_FAIL"));
+
+          #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+          return DECLINED;
+         }
+
+      }/* End 'else' */
+
+    /*
+     * We have the static filename and the length.
+     * That's pretty much all we need at this point so
+     * go ahead and encode/transmit the object...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Call mod_gzip_encode_and_transmit()...\n",cn);
+    #endif
+
+    rc =
+    mod_gzip_encode_and_transmit(
+    (request_rec *) r,           /* request_rec */
+    (char        *) r->filename, /* source ( Filename or Memory buffer ) */
+    (int          ) 1,           /* 1=Source is a file 0=Memory buffer */
+    (long         ) input_size,  /* input_size */
+    (int          ) 0            /* nodecline flag 0=Ok to DECLINE 1=No */
+    );
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Back mod_gzip_encode_and_transmit()...\n",cn);
+    #endif
+
+    /*
+     * The encode/transmit path should have already updated
+     * any relevant 'r->note' values ( if used ) for the transaction
+     * to reflect the results of the operation.
+     *
+     * Just return the result code and finish the transaction.
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    if ( rc == OK )
+      {
+       mod_gzip_printf( "%s: Exit > return( rc = %d OK ) >\n",cn,rc);
+      }
+    else if ( rc == DECLINED )
+      {
+       mod_gzip_printf( "%s: Exit > return( rc = %d DECLINED ) >\n",cn,rc);
+      }
+    else /* HTTP ERROR */
+      {
+       mod_gzip_printf( "%s: Exit > return( rc = %d HTTP_ERROR ) >\n",cn,rc);
+      }
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    return( rc );
+
+}/* End of mod_gzip_static_file_handler() */
+
+int mod_gzip_create_unique_filename(
+mod_gzip_conf *mgc,
+char *target,
+int targetmaxlen
+)
+{
+ /*
+  * Creates a unique work file name.
+  */
+
+ long  process_id = 0;  /* Current Process ID */
+ long  thread_id  = 0;  /* Current thread  ID */
+
+ #ifdef MOD_GZIP_DEBUG1
+ char cn[]="mod_gzip_create_unique_filename()";
+ #endif
+
+ /* Start... */
+
+ #ifdef WIN32
+ process_id = (long) GetCurrentProcessId();
+ thread_id  = (long) GetCurrentThreadId();
+ #else /* !WIN32 */
+ process_id = (long) getpid();
+ thread_id  = (long) process_id; /* TODO: Add pthreads call */
+ #endif /* WIN32 */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Entry...\n",cn );
+ mod_gzip_printf( "%s: target            = %ld\n",cn,(long)target);
+ mod_gzip_printf( "%s: targetmaxlen      = %ld\n",cn,(long)targetmaxlen);
+ mod_gzip_printf( "%s: process_id        = %ld\n",cn,(long)process_id );
+ mod_gzip_printf( "%s: thread_id         = %ld\n",cn,(long)thread_id  );
+ mod_gzip_printf( "%s: mod_gzip_iusn     = %ld\n",cn,(long)mod_gzip_iusn );
+ #endif
+
+ /*
+  * Sanity checks...
+  */
+
+ if ( ( !target ) || ( targetmaxlen == 0 ) )
+   {
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Invalid target or targetmaxlen value.\n",cn);
+    mod_gzip_printf( "%s: Exit > return( 1 ) > ERROR >\n",cn );
+    #endif
+
+    return 1;
+   }
+
+ /*
+  * Use the PROCESS + THREAD ID's and the current IUSN
+  * ( Instance Unique Sequence Number ) transaction ID to
+  * create a one-time only unique output workfile name...
+  */
+
+ sprintf(
+ target,
+ "%s%s_%ld_%ld_%ld.wrk",
+ mgc->cache.root,     /* Either ServerRoot or Config specified dir. */
+ mod_gzip_dirsep,     /* Forward slash for UNIX, backslash for WIN32 */
+ (long) process_id,   /* Current process ID */
+ (long) thread_id,    /* Current thread  ID */
+ (long) mod_gzip_iusn /* Instance Unique Sequence Number */
+ );
+
+ mod_gzip_iusn++; /* Increment Instance Unique Sequence Number */
+
+ if ( mod_gzip_iusn > 999999999L ) mod_gzip_iusn = 1; /* Wrap */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: target = [%s]\n",cn,target);
+ mod_gzip_printf( "%s: Exit > return( 0 ) >\n",cn );
+ #endif
+
+ return 0;
+
+}/* End of mod_gzip_create_unique_filename() */
+
+
+#ifdef MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
+
+int mod_gzip_send_html_command_response(
+request_rec *r, /* Request record */
+char *tmp,      /* Response to send */
+char *ctype     /* Content type string */
+)
+{
+ /* Generic command response transmitter... */
+
+ int  tmplen=0;
+ char content_length[20];
+
+ #ifdef MOD_GZIP_DEBUG1
+ char cn[]="mod_gzip_send_html_command_response()";
+ #endif
+
+ /* Start... */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Entry...\n",cn);
+ mod_gzip_printf( "%s: ctype=[%s]\n",cn,ctype);
+ #endif
+
+ /* Add the length of the response to the output header... */
+ /* The third parameter to ap_table_set() MUST be a string. */
+
+ tmplen = strlen( tmp );
+
+ sprintf( content_length, "%d", tmplen );
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: content_length = [%s]\n",cn,content_length);
+ #endif
+
+ ap_table_set( r->headers_out, "Content-Length", content_length );
+
+ /* Make sure the content type matches this response... */
+
+ r->content_type = ctype; /* Actual type passed by caller */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
+ #endif
+
+ /* Start a timer... */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Call ap_soft_timeout()...\n",cn);
+ #endif
+
+ ap_soft_timeout( "mod_gzip_send_html_command", r );
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Back ap_soft_timeout()...\n",cn);
+ #endif
+    
+ #ifdef MOD_GZIP_COMMANDS_USE_LAST_MODIFIED
+
+ /* Be sure to update the modifcation 'time' to current */
+ /* time before calling 'ap_set_last_modified()'. All that */
+ /* call does is set the r->xxxx value into the output */
+ /* header. It doesn't actually update the time itself. */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Call ap_update_mtime(r,r-finfo.st_mtime)...\n",cn);
+ #endif
+
+ ap_update_mtime( r, r->finfo.st_mtime );
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Back ap_update_mtime(r,r-finfo.st_mtime)...\n",cn);
+ #endif
+
+ /* Update the 'Last modified' stamp in output header... */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Call ap_set_last_modified()...\n",cn);
+ #endif
+
+ ap_set_last_modified(r);
+
+ /* TODO: Add 'no-cache' option(s) to mod_gzip command responses */
+ /* so user doesn't have hit reload to get fresh data. */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Back ap_set_last_modified()...\n",cn);
+ #endif
+
+ #endif /* MOD_GZIP_COMMANDS_USE_LAST_MODIFIED */
+
+ /* Send the HTTP response header... */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Call ap_send_http_header()...\n",cn);
+ #endif
+
+ ap_send_http_header(r);
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Back ap_send_http_header()...\n",cn);
+ #endif
+
+ /* Send the response BODY... */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Sending response...\n%s\n",cn,tmp);
+ #endif
+
+ #ifdef MOD_GZIP_USES_AP_SEND_MMAP
+
+ /* Use ap_send_mmap() call to send the data... */
+
+ ap_send_mmap( tmp, r, 0, tmplen );
+
+ #else /* !MOD_GZIP_USES_AP_SEND_MMAP */
+
+ /* Use ap_rwrite() call to send the data... */
+
+ ap_rwrite( tmp, tmplen, r );
+
+ #endif /* MOD_GZIP_USES_AP_SEND_MMAP */
+
+ /* Clean up and exit... */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Call ap_kill_timeout()...\n",cn);
+ #endif
+
+ ap_kill_timeout(r);
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Back ap_kill_timeout()...\n",cn);
+ mod_gzip_printf( "%s: Exit > return( OK ) >\n",cn);
+ #endif
+
+ return OK;
+
+}/* End of mod_gzip_send_html_command_response() */
+
+#endif /* MOD_GZIP_ALLOWS_INTERNAL_COMMANDS */
+
+static void *
+mod_gzip_create_config( pool *p, server_rec *s )
+{
+    int i;
+
+    mod_gzip_conf *ps = 0;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_create_config()";
+    #endif
+
+    /*
+     * Set all the configuration default values...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    #endif
+
+    /*
+     * Allocate a new config structure...
+     */
+
+    ps = ( mod_gzip_conf * ) ap_pcalloc( p, sizeof( mod_gzip_conf ) );
+
+    /*
+     * Set all default values...
+     */
+
+    ps->req                = 1; /* Default is ON */
+    ps->req_set            = 1; /* Default is ON */
+    ps->do_static_files    = 1; /* Default is ON */
+    ps->do_cgi             = 1; /* Default is ON */
+    ps->keep_workfiles     = 0; /* 1=Keep workfiles 0=No */
+    ps->min_http           = 0; /* 1001=HTTP/1.1 Default=All HTTP levels */
+
+    ps->minimum_file_size  = (long) mod_gzip_minimum_file_size;
+                             /* Minimum file size in bytes */
+    ps->maximum_inmem_size = (long) mod_gzip_maximum_inmem_size;
+                             /* Maximum size for in-memory compression */
+
+    /* Compressed object cache control variables... */
+
+    /* Using these default values the compressed object cache
+    /* can have 2^18 directories (256,000) */
+
+    ps->cache.root = ap_server_root; /* Default DIR is ServerRoot */
+
+    ps->cache.space                = MOD_GZIP_DEFAULT_CACHE_SPACE;
+    ps->cache.space_set            = 0;
+    ps->cache.maxexpire            = MOD_GZIP_DEFAULT_CACHE_MAXEXPIRE;
+    ps->cache.maxexpire_set        = 0;
+    ps->cache.defaultexpire        = MOD_GZIP_DEFAULT_CACHE_EXPIRE;
+    ps->cache.defaultexpire_set    = 0;
+    ps->cache.lmfactor             = MOD_GZIP_DEFAULT_CACHE_LMFACTOR;
+    ps->cache.lmfactor_set         = 0;
+    ps->cache.gcinterval           = -1;
+    ps->cache.gcinterval_set       = 0;
+    ps->cache.dirlevels            = 3;
+    ps->cache.dirlevels_set        = 0;
+    ps->cache.dirlength            = 1;
+    ps->cache.dirlength_set        = 0;
+
+    /* Initialize the include/exclude item map list... */
+
+    /* For now all init values are ZERO but don't use */
+    /* memset() since this may not always be the case. */
+
+    ps->imap_total_entries = 0;
+
+    for ( i=0; i<MOD_GZIP_IMAP_MAXNAMES; i++ )
+       {
+        ps->imap[i].include = 0;
+        ps->imap[i].type    = 0;
+        ps->imap[i].action  = 0;
+        ps->imap[i].name[0] = 0;
+
+       }/* End 'i' loop */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: ps->imap_total_entries = %d\n", cn, ps->imap_total_entries );
+    mod_gzip_printf( "%s: Exit > return( ps ) >\n", cn );
+    #endif
+
+    return ps;
+
+}/* End of mod_gzip_create_config() */
+
+static void *
+mod_gzip_merge_config( pool *p, void *basev, void *overridesv )
+{
+    mod_gzip_conf *ps        = ap_pcalloc(p, sizeof(mod_gzip_conf));
+    mod_gzip_conf *base      = (mod_gzip_conf *) basev;
+    mod_gzip_conf *overrides = (mod_gzip_conf *) overridesv;
+
+    ps->req                  = (overrides->req_set == 0) ? base->req : overrides->req;
+    ps->cache.root           = (overrides->cache.root == NULL) ? base->cache.root : overrides->cache.root;
+    ps->cache.space          = (overrides->cache.space_set == 0) ? base->cache.space : overrides->cache.space;
+    ps->cache.maxexpire      = (overrides->cache.maxexpire_set == 0) ? base->cache.maxexpire : overrides->cache.maxexpire;
+    ps->cache.defaultexpire  = (overrides->cache.defaultexpire_set == 0) ? base->cache.defaultexpire : overrides->cache.defaultexpire;
+    ps->cache.lmfactor       = (overrides->cache.lmfactor_set == 0) ? base->cache.lmfactor : overrides->cache.lmfactor;
+    ps->cache.gcinterval     = (overrides->cache.gcinterval_set == 0) ? base->cache.gcinterval : overrides->cache.gcinterval;
+    ps->cache.dirlevels      = (overrides->cache.dirlevels_set == 0) ? base->cache.dirlevels : overrides->cache.dirlevels;
+    ps->cache.dirlength      = (overrides->cache.dirlength_set == 0) ? base->cache.dirlength : overrides->cache.dirlength;
+
+    return ps;
+
+}/* End of mod_gzip_merge_config() */
+
+/*
+ * Module configuration directive handlers...
+ */
+
+static const char *
+mod_gzip_set_on(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_on()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    if ( ( arg[0] == 'Y' )||( arg[0] == 'y' ) )
+      {
+       /* Set the master 'request control' switches ON... */
+
+       mgc->req     = 1; /* Yes */
+       mgc->req_set = 1; /* Yes */
+      }
+    else /* Set the master 'request control' switches OFF... */
+      {
+       mgc->req     = 0; /* No */
+       mgc->req_set = 0; /* No */
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: mgc->req     = %ld\n", cn, (long) mgc->req );
+    mod_gzip_printf( "%s: mgc->req_set = %ld\n", cn, (long) mgc->req_set );
+    #endif
+
+    return NULL;
+}
+
+static const char *
+mod_gzip_set_keep_workfiles(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_keep_workfiles()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    if ( ( arg[0] == 'Y' )||( arg[0] == 'y' ) )
+      {
+       mgc->keep_workfiles = 1; /* Yes */
+      }
+    else
+      {
+       mgc->keep_workfiles = 0; /* No */
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: mgc->keep_workfiles = %ld\n", cn,
+                   (long) mgc->keep_workfiles );
+    #endif
+
+    return NULL;
+}
+
+static const char *
+mod_gzip_set_min_http(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_min_http()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    mgc->min_http = (int) atoi( arg );
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: mgc->min_http = %ld\n", cn,
+                   (long) mgc->min_http );
+    #endif
+
+    return NULL;
+}
+
+
+static const char *
+mod_gzip_imap_add_item( mod_gzip_conf *mgc, char *arg, int flag1 )
+{
+    int  x;
+    char *p1;
+    int  ch1;
+    int  this_type=0;
+    int  this_action=0;
+    int  this_include=flag1;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_imap_add_item()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: 1 arg=[%s]\n", cn, arg );
+
+    if ( flag1 == 1 )
+      {
+       mod_gzip_printf( "%s: flag1 = %d = INCLUDE\n", cn, flag1 );
+      }
+    else if ( flag1 == 0 )
+      {
+       mod_gzip_printf( "%s: flag1 = %d = EXCLUDE\n", cn, flag1 );
+      }
+    else
+      {
+       mod_gzip_printf( "%s: flag1 = %d = ??? Unknown value\n", cn, flag1 );
+      }
+
+    mod_gzip_printf( "%s: MOD-GZIP_IMAP_MAXNAMES  = %d\n",
+                      cn, MOD_GZIP_IMAP_MAXNAMES );
+
+    mod_gzip_printf( "%s: mgc->imap_total_entries = %d\n",
+                      cn, mgc->imap_total_entries );
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    /*
+     * Parse the config line...
+     */
+
+    p1 = arg;
+    while((*p1!=0)&&(*p1<33)) p1++;
+    ch1 = *p1;
+
+    this_type   = MOD_GZIP_IMAP_ISHANDLER;
+    this_action = MOD_GZIP_IMAP_DYNAMIC1;
+
+    if ( ch1 == '!' )
+      {
+       arg++;
+       p1 = arg;
+       while((*p1!=0)&&(*p1<33)) p1++;
+       ch1 = *p1;
+      }
+    else
+      {
+       this_action = MOD_GZIP_IMAP_STATIC1;
+      }
+
+    if ( ch1 == '.' )
+      {
+       this_type = MOD_GZIP_IMAP_ISEXT;
+      }
+    else
+      {
+       p1 = arg;
+       while (*p1!=0)
+         {
+          if ( *p1 == '/' )
+            {
+             this_type = MOD_GZIP_IMAP_ISMIME;
+            }
+          p1++;
+         }
+      }
+
+    /*
+     * Safety checks...
+     */
+
+    if ( ( this_type != MOD_GZIP_IMAP_ISMIME    ) &&
+         ( this_type != MOD_GZIP_IMAP_ISEXT     ) &&
+         ( this_type != MOD_GZIP_IMAP_ISHANDLER ) )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: this_type = %d = MOD_GZIP_IMAP_IS??? Unknown type\n",cn,this_type);
+       mod_gzip_printf( "%s: return( mod_gzip: ERROR: Unrecognized item 'type'\n",cn);
+       #endif
+
+       return( "mod_gzip: ERROR: Unrecognized item 'type'" );
+      }
+
+    if ( ( this_action != MOD_GZIP_IMAP_DYNAMIC1 ) &&
+         ( this_action != MOD_GZIP_IMAP_STATIC1  ) )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: this_action = %d = MOD_GZIP_IMAP_??? Unknown action\n",cn,this_action);
+       mod_gzip_printf( "%s: return( mod_gzip: ERROR: Unrecognized item 'action'\n",cn);
+       #endif
+
+       return( "mod_gzip: ERROR: Unrecognized item 'action'" );
+      }
+
+    /*
+     * Wildcards...
+     */
+
+     if ( this_type != MOD_GZIP_IMAP_ISMIME )
+       {
+        /*
+         * Wildcards are only allowed in MIME strings such as 'image/*'
+         */
+
+        p1 = arg;
+        while (*p1!=0)
+          {
+           if ( *p1 == '*' )
+             {
+              return( "mod_gzip: ERROR: Wildcards are only allowed in MIME strings." );
+             }
+           p1++;
+          }
+       }
+
+    /*
+     * If there is room for a new record then add it...
+     */
+
+    if ( mgc->imap_total_entries < MOD_GZIP_IMAP_MAXNAMES )
+      {
+       if ( strlen( arg ) < MOD_GZIP_IMAP_MAXNAMELEN )
+         {
+          x = mgc->imap_total_entries;
+
+          p1 = arg;
+          while((*p1!=0)&&(*p1<33)) p1++;
+
+          strcpy( mgc->imap[x].name, p1 );
+
+          mgc->imap[x].include = this_include;
+          mgc->imap[x].type    = this_type;
+          mgc->imap[x].action  = this_action;
+
+          mgc->imap_total_entries++; /* Increase onboard items */
+         }
+       else /* ERROR: Name is too long */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: return( mod_gzip: ERROR: Item name is too long\n",cn);
+          #endif
+
+          return( "mod_gzip: ERROR: Item name is too long" );
+         }
+      }
+    else /* ERROR: INDEX is FULL */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: return( mod_gzip: ERROR: Item index is full\n",cn);
+       #endif
+
+       return( "mod_gzip: ERROR: Item index is full" );
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Exit > return( NULL ) >\n",cn);
+    #endif
+
+    return NULL;
+
+}/* End of mod_gzip_imap_add_item() */
+
+#ifdef MOD_GZIP_DEBUG1
+
+int mod_gzip_imap_show_items( mod_gzip_conf *mgc )
+{
+    /*
+     * DEBUG only. Show the complete include/exclude list.
+     * This is normally called from mod_gzip_init()
+     * after all the configuration routines have executed.
+     */
+
+    int  i;
+    int  x;
+    char cn[]="mod_gzip_imap_show_items()";
+
+    /* Start... */
+
+    mod_gzip_printf( "\n");
+    mod_gzip_printf( "%s: Entry\n", cn );
+
+    mod_gzip_printf( "%s: mgc->imap_total_entries= %d\n", cn,
+                   (long) mgc->imap_total_entries );
+
+    for ( i=0; i<mgc->imap_total_entries; i++ )
+       {
+        x = i; /* Work variable */
+
+        mod_gzip_printf( "\n");
+        mod_gzip_printf( "%s: mgc->imap[%3.3d].include = %d\n",  cn,x,mgc->imap[x].include);
+        mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = %d\n",  cn,x,mgc->imap[x].type);
+
+        if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISMIME )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = MOD_GZIP_IMAP_ISMIME\n",cn,x);
+          }
+        else if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISEXT )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = MOD_GZIP_IMAP_ISEXT\n",cn,x);
+          }
+        else if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISHANDLER )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = MOD_GZIP_IMAP_ISHANDLER\n",cn,x);
+          }
+        else /* Unrecognized item type... */
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = MOD_GZIP_IMAP_IS??? Unknown type\n",cn,x);
+          }
+
+        mod_gzip_printf( "%s: mgc->imap[%3.3d].action  = %d\n",  cn,x,mgc->imap[x].action);
+
+        if ( mgc->imap[x].action == MOD_GZIP_IMAP_DYNAMIC1 )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].action  = MOD_GZIP_IMAP_DYNAMIC1\n",cn,x);
+          }
+        else if ( mgc->imap[x].action == MOD_GZIP_IMAP_STATIC1 )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].action  = MOD_GZIP_IMAP_STATIC1\n",cn,x);
+          }
+        else /* Unrecognized action type... */
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].action  = MOD_GZIP_IMAP_??? Unknown action\n",cn,x);
+          }
+
+        mod_gzip_printf( "%s: mgc->imap[%3.3d].name    = [%s]\n",cn,x,mgc->imap[x].name);
+
+       }/* End 'i' loop */
+
+    mod_gzip_printf( "\n");
+
+    return 0;
+
+}/* End of mod_gzip_imap_show_items() */
+
+#endif /* MOD_GZIP_DEBUG1 */
+
+static const char *
+mod_gzip_set_item_include(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_item_include()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    /* Pass pre-determined pointer to config structure... */
+    /* Pass '1' for parm 3 to INCLUDE this item... */
+
+    return( mod_gzip_imap_add_item( mgc, arg, 1 ) );
+}
+
+static const char *
+mod_gzip_set_item_exclude(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_item_exclude()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    /* Pass pre-determined pointer to config structure... */
+    /* Pass '0' for parm 3 to EXCLUDE this item... */
+
+    return( mod_gzip_imap_add_item( mgc, arg, 0 ) );
+}
+
+static const char *
+mod_gzip_set_temp_dir(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+
+    char cn[]="mod_gzip_set_temp_dir()";
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    mgc->cache.root = arg; /* For now temp dir is used as cache root */
+
+    strcpy( mod_gzip_temp_dir, arg );
+    mgc->cache.root = mod_gzip_temp_dir;
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: mgc->cache.root=[%s]\n", cn, mgc->cache.root );
+    #endif
+
+    return NULL;
+}
+
+static const char *
+mod_gzip_set_minimum_file_size(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+    long lval;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_minimum_file_size()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    lval = (long) atol(arg);
+
+    /* 300 bytes is the minimum at all times */
+    if ( lval < 300L ) lval = 300L;
+
+        mgc->minimum_file_size = (long) lval; /* Set config */
+    mod_gzip_minimum_file_size = (long) lval; /* Set global */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: ....mgc->minimum_file_size = %ld\n", cn,
+                   (long)     mgc->minimum_file_size );
+    mod_gzip_printf( "%s: mod_gzip_minimum_file_size = %ld\n", cn,
+                   (long) mod_gzip_minimum_file_size );
+    #endif
+
+    return NULL;
+}
+
+static const char *
+mod_gzip_set_maximum_inmem_size(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+    long lval=0;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_maximum_inmem_size()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    lval = (long) atol(arg);
+
+    /* 60000 bytes is the current maximum since a malloc() call is used */
+    if ( lval > 60000L ) lval = 60000L;
+
+        mgc->maximum_inmem_size = (long) lval; /* Set config */
+    mod_gzip_maximum_inmem_size = (long) lval; /* Set global */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: ....mgc->maximum_inmem_size = %ld\n", cn,
+                   (long)     mgc->maximum_inmem_size );
+    mod_gzip_printf( "%s: mod_gzip_maximum_inmem_size = %ld\n", cn,
+                   (long) mod_gzip_maximum_inmem_size );
+    #endif
+
+    return NULL;
+}
+
+static const char *
+mod_gzip_set_do_static_files(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_do_static_files()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    if ( ( arg[0] == 'Y' )||( arg[0] == 'y' ) )
+      {
+       mgc->do_static_files = 1; /* Yes */
+      }
+    else
+      {
+       mgc->do_static_files = 0; /* No */
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: mgc->do_static_files = %ld\n", cn,
+                   (long) mgc->do_static_files );
+    #endif
+
+    return NULL;
+}
+
+static const char *
+mod_gzip_set_do_cgi(cmd_parms *parms, void *dummy, char *arg)
+{
+    mod_gzip_conf *mgc;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_set_do_cgi()";
+    #endif
+
+    /* Start... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Entry\n", cn );
+    mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
+    #endif
+
+    mgc = ( mod_gzip_conf * )
+    ap_get_module_config(parms->server->module_config, &gzip_module);
+
+    if ( ( arg[0] == 'Y' )||( arg[0] == 'y' ) )
+      {
+       mgc->do_cgi = 1; /* Yes */
+      }
+    else
+      {
+       mgc->do_cgi = 0; /* No */
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: mgc->do_cgi = %ld\n", cn,
+                   (long) mgc->do_cgi );
+    #endif
+
+    return NULL;
+}
+
+static const handler_rec mod_gzip_handlers[] =
+{
+    /*
+     * This is where we associate an ASCII NAME for our 'handler'
+     * which is what gets set into the r->handler field for a
+     * request and allows the function name associated with the
+     * ASCII name to be called and handle the request...
+     */
+
+    /* Add a 'name' and some types to our handler... */
+
+    {"mod_gzip_handler", mod_gzip_handler},
+    {CGI_MAGIC_TYPE,     mod_gzip_handler},
+    {"cgi-script",       mod_gzip_handler},
+    {"*",                mod_gzip_handler},
+    {NULL}
+};
+
+
+static const command_rec mod_gzip_cmds[] =
+{
+    /*
+     * Define our httpd.conf configuration diectives and
+     * the local routines that are responsible for processing
+     * those directives when the time comes...
+     */
+
+    {"mod_gzip_on", mod_gzip_set_on, NULL, RSRC_CONF, TAKE1,
+     "Yes=mod_gzip will handle requests No=mod_gzip runs in 'passthrough' mode"},
+
+    {"mod_gzip_do_static_files", mod_gzip_set_do_static_files, NULL, RSRC_CONF, TAKE1,
+     "'Yes' means mod_gzip will compress static files."},
+
+    {"mod_gzip_do_cgi", mod_gzip_set_do_cgi, NULL, RSRC_CONF, TAKE1,
+     "'Yes' means mod_gzip will compress dynamic CGI script output."},
+
+    {"mod_gzip_keep_workfiles", mod_gzip_set_keep_workfiles, NULL, RSRC_CONF, TAKE1,
+     "On=Keep work files Off=No"},
+
+    {"mod_gzip_min_http", mod_gzip_set_min_http, NULL, RSRC_CONF, TAKE1,
+     "Minimum HTTP support level to receive compression. 1001=HTTP/1.1"},
+
+    {"mod_gzip_minimum_file_size", mod_gzip_set_minimum_file_size, NULL, RSRC_CONF, TAKE1,
+     "The minimum size ( in bytes ) before compression will be attempted"},
+
+    {"mod_gzip_maximum_inmem_size", mod_gzip_set_maximum_inmem_size, NULL, RSRC_CONF, TAKE1,
+     "The maximum size ( in bytes ) to use for in-memory compression."},
+
+    {"mod_gzip_temp_dir", mod_gzip_set_temp_dir, NULL, RSRC_CONF, TAKE1,
+     "The directory to use for work files and compression cache"},
+
+    {"mod_gzip_item_include", mod_gzip_set_item_include, NULL, RSRC_CONF, TAKE1,
+     "Add the item the inclusion list"},
+
+    {"mod_gzip_item_exclude", mod_gzip_set_item_exclude, NULL, RSRC_CONF, TAKE1,
+     "Add the item the exclusion list"},
+
+    {NULL}
+};
+
+/*
+ * The actual module 'jump' table...
+ *
+ * If one of the fixed 'call' points has a valid function
+ * address then Apache will 'call' into it at the appropriate time.
+ *
+ * When the compressed object cache is engaged we will need to
+ * simply add some handlers for the URI detection and translation
+ * call point(s).
+ */
+
+module MODULE_VAR_EXPORT gzip_module =
+{
+    STANDARD_MODULE_STUFF,
+    mod_gzip_init,          /* initializer */
+    NULL,                   /* create per-directory config structure */
+    NULL,                   /* merge per-directory config structures */
+    mod_gzip_create_config, /* create per-server config structure */
+    mod_gzip_merge_config,  /* merge per-server config structures */
+    mod_gzip_cmds,          /* command table */
+    mod_gzip_handlers,      /* handlers */
+    NULL,                   /* translate_handler */
+    NULL,                   /* check_user_id */
+    NULL,                   /* check auth */
+    NULL,                   /* check access */
+    NULL,                   /* type_checker */
+    NULL,                   /* pre-run fixups */
+    NULL,                   /* logger */
+    NULL,                   /* header parser */
+    NULL,                   /* child_init */
+    NULL,                   /* child_exit */
+    NULL                    /* post read-request */
+};
+
+#ifdef NETWARE
+int main(int argc, char *argv[]) 
+{
+    ExitThread(TSR_THREAD, 0);
+}
+#endif
+
+FILE *mod_gzip_open_output_file(
+request_rec *r,
+char *output_filename,
+int  *rc
+)
+{
+ FILE *ifh;
+
+ #ifdef MOD_GZIP_DEBUG1
+ char cn[]="mod_gzip_open_output_file():::";
+ #endif
+
+ /*
+  * Start...
+  */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: Entry...\n",cn);
+ mod_gzip_printf( "%s: output_filename=[%s]\n",cn,output_filename);
+ #endif
+
+ ifh = fopen( output_filename, "rb" ); /* Open in BINARY mode */
+
+ if ( !ifh ) /* The file failed to open... */
+   {
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: ERROR: Cannot open file [%s]\n",
+                      cn,output_filename);
+    #endif
+
+    /*
+     * The workfile was created OK but now will not re-open.
+     * This is worth a strike in the ERROR log.
+     */
+
+    ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server,
+    "mod_gzip: Cannot re-open output_filename=[%s]",
+    output_filename );
+
+    /* Return DECLINED and let default logic finish the request... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Exit > return( NULL ) >\n",cn);
+    #endif
+
+    #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+    /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+    ap_table_setn(
+    r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:WORK_OPENFAIL"));
+
+    #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+    *rc = DECLINED; /* Update caller's result code... */
+
+    return NULL;
+
+   }/* End 'if ( !ifh )' */
+
+ #ifdef MOD_GZIP_DEBUG1
+ mod_gzip_printf( "%s: File is now open...\n",cn);
+ mod_gzip_printf( "%s: Exit > return( FILE *ifh ) >\n",cn);
+ #endif
+
+ *rc = OK; /* Update caller's result code */
+
+ return ifh; /* Return the file handle */
+
+}/* End of mod_gzip_open_output_file() */
+
+int mod_gzip_encode_and_transmit(
+request_rec *r,
+char        *source,
+int          source_is_a_file,
+long         input_size,
+int          nodecline
+)
+{
+    GZP_CONTROL   gzc;
+    GZP_CONTROL*  gzp = &gzc;
+
+    int             rc                = 0;
+    FILE           *ifh               = 0;
+    int             bytesread         = 0;
+    long            output_size       = 0;
+    long            compression_ratio = 0;
+    char*           gz1_ismem_obuf    = 0;
+    int             finalize_stats    = 1;
+
+    int             gz1_ismem_obuf_was_allocated = 0;
+
+    char content_length[20]; /* For Content-length updates */
+
+    #define MOD_GZIP_LARGE_BUFFER_SIZE 8192
+
+    char tmp[ MOD_GZIP_LARGE_BUFFER_SIZE + 2 ]; /* Scratch buffer */
+
+    char *actual_content_encoding_name = "gzip"; /* Adjustable */
+       const char *compression_format;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_encode_and_transmit()";
+    #endif
+
+    void *modconf = r->server->module_config;
+
+    #ifdef MOD_GZIP_USES_APACHE_LOGS
+    char log_info[40]; /* Scratch buffer */
+    #endif
+
+    /*
+     * Start...
+     *
+     * Establish a local pointer to module configuration data...
+     */
+
+    mod_gzip_conf *conf =
+    (mod_gzip_conf *) ap_get_module_config( modconf, &gzip_module );
+
+    #ifdef MOD_GZIP_DEBUG1
+
+    mod_gzip_printf( "%s: Entry...\n", cn);
+    mod_gzip_printf( "%s: source_is_a_file = %d\n", cn, source_is_a_file);
+    mod_gzip_printf( "%s: nodecline        = %d\n", cn, nodecline);
+
+    if ( source_is_a_file ) /* Show the filename... */
+      {
+       mod_gzip_printf( "%s: source = [%s]\n", cn, source);
+      }
+    else /* Don't try to print the memory buffer... */
+      {
+       mod_gzip_printf( "%s: source = MEMORY BUFFER\n", cn );
+      }
+
+    mod_gzip_printf( "%s: input_size = %ld\n", cn,(long)input_size);
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+
+    #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+    /* This routine 'assumes' that the final result is 'OK' */
+    /* and lets the remainder of the processing set the result */
+    /* string to some other value, if necessary. */
+
+    /* Since we are now using the 'nodecline' flag and might */
+    /* have to 'stand and deliver' then this allows the right */
+    /* result code to appear in the log files even if we */
+    /* cannot DECLINE the processing. */
+
+    ap_table_setn(
+    r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"OK"));
+
+    /* We can also update the 'input' size right away since it is known */
+
+    sprintf( log_info,"%d", (int) input_size );
+    ap_table_setn( r->notes,"mod_gzip_input_size",ap_pstrdup(r->pool,log_info));
+
+    #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+    /*
+     * If the source has no length then DECLINE the processing...
+     */
+
+    if ( input_size < 1 )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: ERROR: Input source has no valid length.\n",cn);
+       mod_gzip_printf( "%s: This request will not be processed...\n",cn);
+       #endif
+
+       /* An existing request object with no length is worth a warning... */
+
+       ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_WARNING, r->server,
+       "mod_gzip: r->filename=[%s] has no length",r->filename );
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+       #endif
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_I_LEN"));
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       return DECLINED;
+      }
+
+       /*
+     * If we're only supposed to send header information (HEAD request)
+     * then all we need to do is call ap_send_http_header() at this point
+     * and then return 'OK'...
+     */
+
+    if ( r->header_only )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: HEAD request only... ignore body data...\n",cn);
+       #endif
+
+       /*
+        * Set outbound response header fields...
+        *
+        * NOTE: If this is just a HEAD request then
+        * there is no need to make the API call...
+        *
+        * ap_update_mtime( r, r->finfo.st_mtime );
+        *
+        * ...and update the actual time. Use the time
+        * that's currently associated with the object.
+        */
+
+       ap_set_last_modified(r);
+       ap_set_etag(r);
+       ap_table_setn(r->headers_out, "Accept-Ranges", "bytes");
+
+       /* Start a timer for this transaction... */
+
+       ap_soft_timeout( "mod_gzip: HEAD request handler", r );
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: r->content_type=[%s]\n",cn,r->content_type);
+       mod_gzip_printf( "%s: Call ap_send_http_header()...\n",cn);
+       #endif
+
+       ap_send_http_header(r);
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Back ap_send_http_header()...\n",cn);
+       mod_gzip_printf( "%s: Call ap_kill_timeout()...\n",cn);
+       #endif
+
+       ap_kill_timeout(r);
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Back ap_kill_timeout()...\n",cn);
+       mod_gzip_printf( "%s: Exit > return( OK ) >\n",cn);
+       #endif
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Return OK but distinguish it from a 'GET' request in logs...  */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"OK:HEAD_ONLY"));
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       return OK;
+
+      }/* End 'if( r->header_only )' */
+
+    /*
+     * See if the source meets the MINUMUM SIZE requirement...
+     *
+     * Default to 300 bytes as a minimum size requirement for it
+     * to even be worth a compression attempt. This works well as a
+     * minimum for both GZIP and ZLIB which are both LZ77 based and,
+     * as such, always have the potential to actually increase the
+     * size of the file.
+     *
+     * The value is a module global that can be adjusted 'on the fly'
+     * as load conditions change or as required for other reasons.
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: conf->minimum_file_size = %ld\n",
+               cn, (long) conf->minimum_file_size );
+    #endif
+
+    if ( input_size < (long) conf->minimum_file_size )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Source does not meet the minimum size requirement...\n",cn);
+       mod_gzip_printf( "%s: nodecline = %d\n",cn,nodecline);
+       #endif
+
+       /* Set the 'mod_gzip_result' note value to something */
+       /* that indicates this was too small... */
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:TOO_SMALL"));
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       /* Is it OK to DECLINE?... */
+
+       if ( nodecline ) /* We have been told NOT to DECLINE */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: DECLINE is NOT allowed...\n",cn);
+          #endif
+
+          /* Skip the compression phase and just set the output */
+          /* control skid up to send the real input data... */
+
+          output_size = input_size;
+
+          if ( source_is_a_file ) /* Source is a workfile... */
+            {
+             #ifdef MOD_GZIP_DEBUG1
+             mod_gzip_printf( "%s: Force send - source = FILE[%s]\n",
+                              cn,source);
+             #endif
+
+             strcpy( gzp->output_filename, source );
+             gzp->output_ismem         = 0; /* Output is a disk file */
+             gz1_ismem_obuf            = 0; /* Make sure this is NULL */
+             gzp->output_ismem_obuf    = 0; /* Not used for this method */
+             gzp->output_ismem_obuflen = 0; /* Not used for this method */
+
+             ifh = mod_gzip_open_output_file( r, gzp->output_filename, &rc );
+
+             if ( !ifh ) /* The file failed to open... */
+               {
+                /* We really MUST decline... */
+                /* Logs have already been updated... */
+
+                return( rc );
+               }
+            }
+          else /* Source is just a memory buffer... */
+            {
+             #ifdef MOD_GZIP_DEBUG1
+             mod_gzip_printf( "%s: Force send - source = MEMORY BUFFER\n",cn);
+             #endif
+
+             gzp->output_ismem = 1;
+             gz1_ismem_obuf    = source;
+
+             gz1_ismem_obuf_was_allocated = 0; /* No 'free' is required */
+            }
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: No compression attempt was made.\n",cn);
+          mod_gzip_printf( "%s: Advancing directly to transmit phase...\n",cn);
+          #endif
+
+          goto mod_gzip_encode_and_transmit_send_start; /* Jump */
+         }
+       else /* It's OK to DECLINE the processing... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: DECLINE is allowed...\n",cn);
+          mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+          #endif
+
+          return DECLINED;
+         }
+      }
+    else /* The source is larger than the minimum size requirement... */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Source meets the minimum size requirement.\n",cn);
+       mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
+       #endif
+      }
+
+    /*
+     * We must now encode the requested object...
+     *
+     * Statistically speaking, most 'text/*' pages are
+     * less than 60k. XML documents are an exception.
+     *
+     * If the size of the requested object is less than 60k
+     * then go ahead and compress the source directly to a
+     * small memory buffer. If the requested object is greater
+     * than 60k then go ahead and swap the results to an output
+     * disk file and then send the contents of the result file.
+     *
+     * We can't ever allocate all the memory we want inside of
+     * a Server task thread so there must always be this kind
+     * of 'decision' making about when we can compress to
+     * a memory buffer ( Less than 60k ) and when we must
+     * compress to DISK. ( Greater than 60k ).
+     *
+     * There is a trade-off here between running the risk of
+     * too many tasks stealing away all the heap space and
+     * still maintaining performance. Given all the variables
+     * involved such as the true efficiency of the compression
+     * algorithm(s) and the speed of the CPU and the amount of
+     * memory/disk space available there is no 'real' answer to
+     * this dilemma other than relying on statistical data
+     * and empirical observations. The 60k limit on in-memory
+     * compression seems to strike a good balance and performs
+     * incredibly well under the heaviest of loads.
+     *
+     * At all times, the greatest benefit being gained is the
+     * appreciable reduction of data that must actually be
+     * sent by the TCP/IP sub-system and the reduced usage
+     * of those resources to perform the transmission task(s),
+     *
+     * The key, then, is to always strive for a balance where
+     * the time and resource usage it takes to compress a
+     * deliverable object will always be less than the processor
+     * burden that would otherwise be realized by handing the
+     * full, uncompressed object to the TCP/IP sub-system which
+     * always extend the time that the thread and all its
+     * locked resources must be maintained as well as the
+     * overhead for keeping a connection active any longer
+     * than is absolutely necessary.
+     *
+     * As long as the resource usage it takes to accomplish
+     * a significant reduction in the amount of data that
+     * must actually be processed by the remainder of the
+     * HTTP task thread and the TCP/IP sub-system itself
+     * is always less than the processor burden seen by
+     * NOT doing so then we are always 'ahead of the game'.
+     */
+
+    /*
+     * See if the object size exceeds the current MAXIMUM size
+     * to use for in-memory compression...
+     *
+     * See notes above about a range of 60k or so being the best
+     * value for heavy load conditions.
+     *
+     * This number is currently a global so it can be changed
+     * 'on the fly' and can 'breathe' as the load changes.
+     * It should probably become a thread specific variable
+     * so each task can have its 'own' max value depending
+     * on current load conditions.
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: conf->maximum_inmem_size = %ld\n",
+               cn, (long) conf->maximum_inmem_size );
+    #endif
+
+    /*
+     * Set up the INPUT target...
+     */
+
+    /* The size and type of the input source is always known */
+    /* and was passed by the caller... */
+
+    if ( source_is_a_file )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Input source is file[%s]\n",cn,source);
+       #endif
+
+       strcpy( gzp->input_filename, source );
+
+       gzp->input_ismem         = 0; /* Input is a disk file */
+       gzp->input_ismem_ibuf    = 0; /* Source buffer */
+       gzp->input_ismem_ibuflen = 0; /* Length of data */
+      }
+    else
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Input source is a MEMORY BUFFER\n",cn);
+       #endif
+
+       *gzp->input_filename = 0; /* Not used */
+
+       gzp->input_ismem         = 1;          /* Input is a memory buffer */
+       gzp->input_ismem_ibuf    = source;     /* Source buffer */
+       gzp->input_ismem_ibuflen = input_size; /* Length of data */
+      }
+
+    /*
+     * Set up the OUTPUT target...
+     */
+
+    gzp->decompress = 0; /* Perform encoding */
+
+       /* Recover the compression format we're supposed to use. */
+       compression_format = ap_table_get(r->notes, "mod_gzip_compression_format");
+       if (compression_format && strcmp(compression_format, "deflate") == 0)
+         {
+          actual_content_encoding_name = "deflate";
+          gzp->compression_format = DEFLATE_FORMAT;
+      }
+    else
+         {
+          gzp->compression_format = GZIP_FORMAT;
+      }
+
+    if ( input_size <= (long) conf->maximum_inmem_size )
+      {
+       /* The input source is small enough to compress directly */
+       /* to an in-memory output buffer... */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Input source is small enough for in-memory compression.\n",cn);
+       #endif
+
+       *gzp->output_filename = 0; /* Not used */
+        gzp->output_ismem    = 1; /* Output is a memory buffer */
+
+       /*
+        * Allocate a memory buffer to hold compressed output.
+        *
+        * For now this is borrowed from the heap for only
+        * the lifetime of this function call. If the stack
+        * can handle the current in-memory MAXSIZE then
+        * that will work just as well.
+        *
+        * Add at least 1000 bytes in case the compression
+        * algorithm(s) actually expands the source ( which is
+        * not likely but is always a possibility when using
+        * any LZ77 based compression such as GZIP or ZLIB )
+        */
+
+       gz1_ismem_obuf = (char *) malloc( input_size + 1000 );
+
+       if ( !gz1_ismem_obuf )
+         {
+          /*
+           * There wasn't enough memory left for another
+           * in-memory compression buffer so default to using
+           * an output disk file instead...
+           */
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: ERROR: Cannot allocate GZP memory...\n",cn);
+          mod_gzip_printf( "%s: Defaulting to output file method... \n",cn);
+          #endif
+
+          gzp->output_ismem = 0; /* Switch to using a disk file */
+         }
+
+       else /* We got the memory we need for in-memory compression... */
+         {
+          /* Set the local flag which tells the exit logic */
+          /* that 'gz1_ismem_obuf' was actually allocated */
+          /* and not simply set to 'source' so that the */
+          /* allocation can be 'freed' on exit... */
+
+          gz1_ismem_obuf_was_allocated = 1; /* 'free' is required */
+
+          /* Compression codecs require a 'clean' buffer so */
+          /* we need to spend the cycles for a memset() call. */
+
+          memset( gz1_ismem_obuf, 0, ( input_size + 1000 ) );
+
+          /* Set OUTPUT buffer control variables... */
+
+          gzp->output_ismem_obuf    = gz1_ismem_obuf;
+          gzp->output_ismem_obuflen = input_size + 1000;
+         }
+
+      }/* End 'if ( input_size <= conf->maximum_inmem_size )' */
+
+    /*
+     * If we are unable ( or it is unadvisable ) to use
+     * an in-memory output buffer at this time then the
+     * 'gzp->output_ismem' flag will still be ZERO at this point.
+     */
+
+    if ( gzp->output_ismem != 1 )
+      {
+       /*
+        * The input source is NOT small enough to compress to an
+        * in-memory output buffer or it is unadvisable to do
+        * so at this time so just use an output file...
+        */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Input source too big for in-memory compression.\n",cn);
+       #endif
+
+       /*
+        * Create the GZP output target name...
+        */
+
+       mod_gzip_create_unique_filename(
+       (mod_gzip_conf *) conf,
+       (char *) gzp->output_filename,
+       MOD_GZIP_MAX_PATH_LEN
+       );
+
+       /*
+        * COMPRESSION OBJECT CACHE
+        *
+        * TODO: Obviously one place to add the compression cache
+        * logic is right here. If there is already a pre-compressed
+        * version of the requested entity sitting in the special
+        * compression cache and it is 'fresh' then go ahead and
+        * send it as the actual response. Add a CRC/MD5 checksum
+        * to the stored compression object(s) so we can quickly
+        * determine if the compressed object is 'fresh'. Relying
+        * on Content-length and/or modification time/date won't handle
+        * all possible expiration scenarios for compressed objects.
+        */
+
+       gzp->output_ismem = 0; /* Output is a disk file */
+
+       gz1_ismem_obuf    = 0; /* Make sure this is NULL */
+
+       /* Set OUTPUT buffer control variables... */
+
+       gzp->output_ismem_obuf    = 0; /* Not used for this method */
+       gzp->output_ismem_obuflen = 0; /* Not used for this method */
+
+      }/* End 'else' */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: gzp->decompress      = %d\n"  ,cn,gzp->decompress);
+    mod_gzip_printf( "%s: gzp->compression_format = %d\n",cn,gzp->compression_format);
+    mod_gzip_printf( "%s: gzp->input_ismem     = %d\n",  cn,gzp->input_ismem);
+    mod_gzip_printf( "%s: gzp->output_ismem    = %d\n",  cn,gzp->output_ismem);
+    mod_gzip_printf( "%s: gzp->input_filename  = [%s]\n",cn,gzp->input_filename);
+    mod_gzip_printf( "%s: gzp->output_filename = [%s]\n",cn,gzp->output_filename);
+    mod_gzip_printf( "%s: Call gzp_main()...\n",cn);
+    #endif
+
+    rc = gzp_main( gzp ); /* Perform the compression... */
+
+    output_size = (long) gzp->bytes_out;
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Back gzp_main()...\n",cn);
+    mod_gzip_printf( "%s: input_size     = %ld\n",cn,(long)input_size);
+    mod_gzip_printf( "%s: output_size    = %ld\n",cn,(long)output_size);
+    mod_gzip_printf( "%s: gzp->bytes_out = %ld\n",cn,(long)gzp->bytes_out);
+    mod_gzip_printf( "%s: Bytes saved    = %ld\n",cn,
+                     (long)input_size-gzp->bytes_out );
+    #endif
+
+    /* Compute the compresion ratio for access.log and */
+    /* internal statistics update... */
+
+    compression_ratio = 0; /* Reset */
+
+    /* Prevent 'Divide by zero' error... */
+
+    if ( ( input_size  > 0 ) &&
+         ( output_size > 0 ) )
+      {
+       compression_ratio = 100 - (int)
+       ( output_size * 100L / input_size );
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Compression ratio = %ld percent\n",cn,
+             (long) compression_ratio );
+    #endif
+
+    /*
+     * Update the logs with output size information
+     * as soon as it is known in case there was an
+     * error or we must DECLINE. At least the logs
+     * will then show the sizes and the results.
+     */
+
+    #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+    sprintf( log_info,"%d", (int) output_size );
+    ap_table_setn( r->notes,"mod_gzip_output_size",ap_pstrdup(r->pool,log_info));
+
+    sprintf( log_info,"%d", (int) compression_ratio );
+    ap_table_setn( r->notes,"mod_gzip_compression_ratio",ap_pstrdup(r->pool,log_info));
+
+    #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+    /*
+     * Evaluate the compression result(s)...
+     *
+     * If the compression pass failed then the output length
+     * will be ZERO bytes...
+     */
+
+    if ( output_size < 1 )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Compressed version has no length.\n",cn);
+       mod_gzip_printf( "%s: Sending the original version uncompressed...\n",cn);
+       #endif
+
+       finalize_stats = 0; /* Don't update stats again */
+
+       if ( r->server->loglevel == APLOG_DEBUG )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "mod_gzip: gzp_main(ERR): r->uri=[%s] input_size=%ld output_size=%ld gzp->output_filename=[%s]",
+           r->uri,(long)input_size,(long)output_size,gzp->output_filename);
+         }
+
+       /*
+        * NOTE: It's perfectly possible that we have made it all
+        * the way to here and the straight execution of the
+        * compressor is the first time there has been a check for
+        * the actual existence of the requested object. This will
+        * be especially true for STATIC requests.
+        *
+        * The compressor itself will fail if/when it can't find
+        * the input target so 'DECLINED:NO_O_LEN' could simply
+        * means the file was not found. In these cases the Apache
+        * logs should also contain the correct '404 Not Found' code.
+        */
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_O_LEN"));
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       /* Is it OK to DECLINE?... */
+
+       if ( nodecline ) /* We have been told NOT to DECLINE... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: DECLINE is NOT allowed...\n",cn);
+          #endif
+
+          /* Just set the output control skid */
+          /* to send the real input data... */
+
+          output_size = input_size;
+
+          if ( source_is_a_file ) /* Source is a workfile... */
+            {
+             strcpy( gzp->output_filename, source );
+
+             gzp->output_ismem         = 0; /* Output is a disk file */
+             gz1_ismem_obuf            = 0; /* Make sure this is NULL */
+             gzp->output_ismem_obuf    = 0; /* Not used for this method */
+             gzp->output_ismem_obuflen = 0; /* Not used for this method */
+
+             ifh = mod_gzip_open_output_file( r, gzp->output_filename, &rc );
+
+             if ( !ifh ) /* We really must DECLINE... */
+               {
+                return( rc );
+               }
+            }
+          else /* Source is just a memory buffer... */
+            {
+             gzp->output_ismem = 1;
+             gz1_ismem_obuf    = source;
+            }
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: Advancing directly to transmit phase...\n",cn);
+          #endif
+
+          goto mod_gzip_encode_and_transmit_send_start; /* Jump */
+         }
+       else /* It's OK to DECLINE the processing... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: DECLINE is allowed...\n",cn);
+          mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+          #endif
+
+          /* Free the local memory buffer allocation ( if necessary )... */
+
+          if ( gz1_ismem_obuf )
+            {
+             /* The pointer may have been 'borrowed' and was */
+             /* not actually 'allocated' so check the flag... */
+
+             if ( gz1_ismem_obuf_was_allocated )
+               {
+                free( gz1_ismem_obuf );
+
+                gz1_ismem_obuf = 0;
+                gz1_ismem_obuf_was_allocated = 0;
+
+               }/* End 'if( gz1_ismem_obuf_was_allocated )' */
+
+            }/* End 'if( gz1_ismem_obuf )' */
+
+          /* Return... */
+
+          return DECLINED;
+         }
+
+      }/* End 'if( output_size < 1 )' */
+
+    /*
+     * If we reach this point then the compressed version has
+     * a valid length. Time to see if it it's worth sending.
+     *
+     * If the original source is SMALLER than the COMPRESSED
+     * version ( not likely but possible with LZ77 ) then
+     * just punt and send the original source...
+     */
+
+    if ( output_size > input_size )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Compressed version is larger than original.\n",cn);
+       mod_gzip_printf( "%s: Sending the original version uncompressed...\n",cn);
+       #endif
+
+       finalize_stats = 0; /* Don't update stats again */
+
+       #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+       /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
+
+       ap_table_setn(
+       r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:ORIGINAL_SMALLER"));
+
+       #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+       /* Is it OK to DECLINE?... */
+
+       if ( nodecline ) /* We have been told NOT to DECLINE... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: DECLINE is NOT allowed...\n",cn);
+          #endif
+
+          /* Just set the output control skid */
+          /* to send the real input data... */
+
+          output_size = input_size;
+
+          if ( source_is_a_file ) /* Source is a workfile... */
+            {
+             strcpy( gzp->output_filename, source );
+
+             gzp->output_ismem         = 0; /* Output is a disk file */
+             gz1_ismem_obuf            = 0; /* Make sure this is NULL */
+             gzp->output_ismem_obuf    = 0; /* Not used for this method */
+             gzp->output_ismem_obuflen = 0; /* Not used for this method */
+
+             ifh = mod_gzip_open_output_file( r, gzp->output_filename, &rc );
+
+             if ( !ifh ) /* We really must DECLINE... */
+               {
+                return( rc );
+               }
+            }
+          else /* Source is just a memory buffer... */
+            {
+             gzp->output_ismem = 1;
+             gz1_ismem_obuf    = source;
+
+             gz1_ismem_obuf_was_allocated = 0; /* No 'free' is required */
+            }
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: Advancing directly to transmit phase...\n",cn);
+          #endif
+
+          goto mod_gzip_encode_and_transmit_send_start; /* Jump */
+         }
+       else /* It's OK to DECLINE the processing... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: DECLINE is allowed...\n",cn);
+          mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+          #endif
+
+          /* Free the local memory buffer allocation ( if necessary )... */
+
+          if ( gz1_ismem_obuf )
+            {
+             /* The pointer may have been 'borrowed' and was */
+             /* not actually 'allocated' so check the flag... */
+
+             if ( gz1_ismem_obuf_was_allocated )
+               {
+                free( gz1_ismem_obuf );
+
+                gz1_ismem_obuf = 0;
+                gz1_ismem_obuf_was_allocated = 0;
+
+               }/* End 'if( gz1_ismem_obuf_was_allocated )' */
+
+            }/* End 'if( gz1_ismem_obuf )' */
+
+          /* Return... */
+
+          return DECLINED;
+         }
+      }
+    else /* Compressed version is smaller than original... */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Compressed version is smaller than original.\n",cn);
+       mod_gzip_printf( "%s: Sending the compressed version...\n",cn);
+       #endif
+      }
+
+    /*
+     * If an output workfile was used then make SURE it is going
+     * to reopen before beginning the transmit phase.
+     *
+     * If we begin the transmit phase before discovering a problem
+     * re-opening the workfile then we have lost the chance to
+     * DECLINE the processing and allow the default logic to
+     * deliver the requested object.
+     *
+     * This only matters for 'static' files or times when the
+     * 'nodecline' flag is FALSE and it is actually OK to DECLINE.
+     */
+
+    if ( !gzp->output_ismem ) /* Workfile was used... */
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Opening compressed output file [%s]...\n",
+                cn, gzp->output_filename );
+       #endif
+
+       ifh = mod_gzip_open_output_file( r, gzp->output_filename, &rc );
+
+       if ( !ifh ) /* The file failed to open... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: ERROR: Cannot re-open file [%s]\n",
+                   cn,gzp->output_filename);
+          #endif
+
+          /* We really must DECLINE... */
+          /* Logs have already been updated... */
+
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+          #endif
+
+          return DECLINED;
+
+         }/* End 'if ( !ifh )' */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Workile re-opened OK...\n",cn);
+       #endif
+
+      }/* End 'if ( !gzp->output_ismem )' */
+
+    /*
+     * IMPORTANT
+     *
+     * If we have made it to here then all is well and only
+     * now can we set the encoding for this response...
+     *
+     * We must do this 'above' any jump points that might
+     * be sending the 'untouched' data or the browser will
+     * get confused regarding the actual content.
+     */
+
+    r->content_encoding = actual_content_encoding_name;
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: r->content_encoding is now [%s]\n",
+                      cn, r->content_encoding );
+    #endif
+
+    /*
+     * Begin the transmission phase...
+     *
+     * Even if the 'nodecline' flag is TRUE if we encounter
+     * any fatal errors at this point we must 'DECLINE'.
+     */
+
+    mod_gzip_encode_and_transmit_send_start: ; /* <<-- Jump point */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Starting transmit phase...\n",cn);
+    #endif
+
+    /*
+     * We are ready to send content so update the "Content-length:"
+     * response field and send the HTTP header. We don't need to
+     * worry about setting the "Content-type:" field since we are
+     * simply accepting the value that was passed to us as indicated
+     * by the inbound r->content_type string. The "Content-type:"
+     * field never changes even when multiple encodings have been
+     * applied to the content itself.
+     *
+     * This version does not make any attempt to use 'Chunked'
+     * transfer encoding since there are so many user agents that
+     * do not support it and when Content-length is known prior
+     * to header transmission ( as is always the case with this
+     * code ) then there is simply no reason to even think about
+     * using the slower and more problematic 'Chunked' encoding
+     * transfer method.
+     */
+
+    /*
+     * Set relevant outbound response header fields...
+     *
+     * Be sure to call ap_update_mtime() before calling
+     * ap_set_last_modified() to be sure the 'current'
+     * time is actually updated in outbound response header.
+     */
+
+    ap_update_mtime( r, r->finfo.st_mtime );
+    ap_set_last_modified(r);
+    ap_set_etag(r);
+    ap_table_setn(r->headers_out, "Accept-Ranges", "bytes");
+
+    /*
+     * Start a timer for this transaction...
+     */
+
+    ap_soft_timeout( "mod_gzip: Encoded data transmit", r );
+
+    /*
+     * Return the length of the compressed output in
+     * the response header.
+     *
+     * See notes above about there never being a requirement
+     * to use 'Chunked' transfer encoding since the content
+     * length is always 'known' prior to transmission.
+     */
+
+    sprintf( content_length, "%ld", output_size );
+    ap_table_set (r->headers_out, "Content-Length", content_length );
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: output_size     = %ld\n",cn,(long)output_size);
+    mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
+    mod_gzip_printf( "%s: Call ap_send_http_header()...\n",cn);
+    #endif
+
+    ap_send_http_header(r);
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Back ap_send_http_header()...\n",cn);
+    #endif
+
+       /*
+     * Send the response...
+     *
+     * If the requested object was small enough to fit into
+     * our special in-memory output space then send the result
+     * directly from memory. If the requested object exceeded
+     * the minimum size for in-memory compression then an output
+     * file was used so re-open and send the results file...
+     */
+
+    if ( gzp->output_ismem )
+      {
+       /* Send the in-memory output buffer... */
+
+       #ifdef MOD_GZIP_DEBUG1
+
+       mod_gzip_printf( "%s: Sending the in-memory output buffer...\n",cn);
+       mod_gzip_printf( "%s: output_size = %ld\n",cn,(long)output_size);
+
+       /* Turn this 'on' for VERY verbose diagnostics...
+       #define MOD_GZIP_DUMP_JUST_BEFORE_SENDING
+       */
+       #ifdef  MOD_GZIP_DUMP_JUST_BEFORE_SENDING
+       mod_gzip_hexdump( gz1_ismem_obuf, output_size );
+       #endif
+
+       #endif /* MOD_GZIP_DEBUG1 */
+
+       /* This module can use either ap_send_mmap() or ap_rwrite()... */
+
+       #ifdef MOD_GZIP_USES_AP_SEND_MMAP
+
+       /* Use ap_send_mmap() call to send the data... */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Call ap_send_mmap( gz1_ismem_obuf, bytes=%ld )...\n",
+                cn, (long)output_size );
+       #endif
+
+       ap_send_mmap( gz1_ismem_obuf, r, 0, output_size );
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Back ap_send_mmap( gz1_ismem_obuf, bytes=%ld )...\n",
+                cn, (long)output_size );
+       #endif
+
+       #else /* !MOD_GZIP_USES_AP_SEND_MMAP */
+
+       /* Use ap_rwrite() call to send the data... */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Call ap_rwrite( gz1_ismem_obuf, bytes=%ld )...\n",
+                cn, (long)output_size );
+       #endif
+
+       ap_rwrite( gz1_ismem_obuf, output_size, r );
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Back ap_rwrite( gz1_ismem_obuf, bytes=%ld )...\n",
+                cn, (long)output_size );
+       #endif
+
+       #endif /* MOD_GZIP_USES_AP_SEND_MMAP */
+
+       /* Stop the timer... */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Call ap_kill_timeout()...\n",cn);
+       #endif
+
+       ap_kill_timeout(r);
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Back ap_kill_timeout()...\n",cn);
+       #endif
+
+       /* Free the local memory buffer allocation ( if necessary )... */
+
+       if ( gz1_ismem_obuf )
+         {
+          /* The pointer may have been 'borrowed' and was */
+          /* not actually 'allocated' so check the flag... */
+
+          if ( gz1_ismem_obuf_was_allocated )
+            {
+             free( gz1_ismem_obuf );
+
+             gz1_ismem_obuf = 0;
+             gz1_ismem_obuf_was_allocated = 0;
+
+            }/* End 'if( gz1_ismem_obuf_was_allocated )' */
+
+         }/* End 'if( gz1_ismem_obuf )' */
+      }
+    else /* Output workfile was used so send the contents... */
+      {
+       /*
+        * NOTE: The workfile was already 're-opened' up above
+        * before the transmit phase began so that we still had
+        * the chance to return DECLINED if, for some reason, the
+        * workfile could not be re-opened.
+        */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: sizeof( tmp )        = %d\n",cn,sizeof(tmp));
+       mod_gzip_printf( "%s: Transmit buffer size = %d\n",cn,sizeof(tmp));
+       mod_gzip_printf( "%s: Sending compressed output file...\n",cn);
+       #endif
+
+       for (;;)
+          {
+           bytesread = fread( tmp, 1, sizeof( tmp ), ifh );
+
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: Back fread(): bytesread=%d\n",cn,bytesread);
+           #endif
+
+           if ( bytesread < 1 ) break; /* File is exhausted... We are done...*/
+
+           /* This module can use either ap_send_mmap() or ap_rwrite()... */
+
+           #ifdef MOD_GZIP_USES_AP_SEND_MMAP
+
+           /* Use ap_send_mmap() call to send the data... */
+
+           ap_send_mmap( tmp, r, 0, bytesread );
+
+           #else /* !MOD_GZIP_USES_AP_SEND_MMAP */
+
+           /* Use ap_rwrite() call to send the data... */
+
+           ap_rwrite( tmp, bytesread, r );
+
+           #endif /* MOD_GZIP_USES_AP_SEND_MMAP */
+          }
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Done Sending compressed output file...\n",cn);
+       mod_gzip_printf( "%s: Closing workfile [%s]...\n",
+                cn, gzp->output_filename );
+       #endif
+
+       fclose( ifh ); /* Close the input file */
+
+       /* Stop the timer before attempting to delete the workfile... */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Call ap_kill_timeout()...\n",cn);
+       #endif
+
+       ap_kill_timeout(r);
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Back ap_kill_timeout()...\n",cn);
+       #endif
+
+       /* Delete the workfile if 'keep' flag is OFF... */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: conf->keep_workfiles = %d\n",
+                         cn, conf->keep_workfiles );
+       #endif
+
+       if ( !conf->keep_workfiles ) /* Default is OFF */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: Deleting workfile [%s]...\n",
+                   cn, gzp->output_filename );
+          #endif
+
+          #ifdef WIN32
+          DeleteFile( gzp->output_filename );
+          #else /* !WIN32 */
+          unlink( gzp->output_filename );
+          #endif /* WIN32 */
+         }
+       else /* Keep all work files... */
+         {
+          #ifdef MOD_GZIP_DEBUG1
+          mod_gzip_printf( "%s: Keeping workfile [%s]...\n",
+                   cn, gzp->output_filename );
+          #endif
+         }
+
+      }/* End 'else' that sends compressed workfile */
+
+    /*
+     * The compressed object has been sent...
+     */
+
+    #ifdef MOD_GZIP_USES_APACHE_LOGS
+
+    if ( finalize_stats )
+      {
+       sprintf( log_info,"%d", (int) output_size );
+       ap_table_setn( r->notes,"mod_gzip_output_size",ap_pstrdup(r->pool,log_info));
+
+       sprintf( log_info,"%d", (int) compression_ratio );
+       ap_table_setn( r->notes,"mod_gzip_compression_ratio",ap_pstrdup(r->pool,log_info));
+
+      }
+    #endif /* MOD_GZIP_USES_APACHE_LOGS */
+
+    if ( r->server->loglevel == APLOG_DEBUG )
+      {
+       /*
+        * If LogLevel is 'debug' then show the compression results
+        * in the log(s)...
+        */
+
+       ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+       "mod_gzip: r->uri=[%s] OK: Bytes In:%ld Out:%ld Compression: %ld pct.",
+       r->uri,
+       (long) input_size,
+       (long) output_size,
+       (long) compression_ratio
+       );
+
+      }/* End 'if( r->server->loglevel == APLOG_DEBUG )' */
+
+    /*
+     * Return OK to the Server to indicate SUCCESS...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Exit > return( OK ) >\n",cn);
+    #endif
+
+    return OK;
+
+}/* End of mod_gzip_encode_and_transmit() */
+
+int mod_gzip_ismatch( char *s1, char *s2, int len1, int haswilds )
+{
+ /* Behaves just like strncmp() but IGNORES differences     */
+ /* between FORWARD or BACKWARD slashes in a STRING, allows */
+ /* wildcard matches, and can ignore length value.          */
+ /* It uses pointers and is faster than using lib calls.    */
+
+ /* Unlike strncmp() this routine returns TRUE (1) if the   */
+ /* strings match and FALSE (0) if they do not...           */
+
+ int  i;
+ int  l1;
+ int  l2;
+ int  distance;
+ char ch1;
+ char ch2;
+
+ /* WARNING! We MUST have a check for 'NULL' on the pointer(s) */
+ /*          themselves or we might GP */
+
+ if ( ( s1 == 0 ) || ( s2 == 0 ) )
+   {
+    /* SAFETY! If pointer itself if NULL */
+    /* don't enter LOOP... */
+
+    return( 0 ); /* Return FALSE for NOMATCH...  */
+   }
+
+ distance = len1; /* Default to value passed... */
+
+ /* If no length was given then the 2 strings must already */
+ /* have the same length or this is a 'no match'... */
+ /* Exception to this is if wildcards are present. */
+
+ if ( len1 == 0 )
+   {
+    l1 = strlen( s1 );
+    l2 = strlen( s2 );
+
+    /* If either string had a valid pointer but is EMPTY */
+    /* then this is an automatic 'no match'... */
+
+    if ((l1==0)||(l2==0))
+      {
+       return( 0 ); /* Return FALSE for NOMATCH...  */
+      }
+
+    if ( l1 != l2  )
+      {
+       if ( haswilds == 0 )
+         {
+          return( 0 ); /* Return FALSE for NOMATCH...  */
+         }
+      }
+
+    /* If the lengths ARE equal then this is a possible */
+    /* match. Use the smaller of the 2 values for scan...*/
+
+    if ( l1 < l2 ) distance = l1;
+    else           distance = l2;
+   }
+
+ /* Final check... if distance is still 0 then this */
+ /* is an automatic 'no match'... */
+
+ if ( distance == 0 )
+   {
+    return( 0 ); /* Return FALSE for NOMATCH...  */
+   }
+
+ /* Do the deed... */
+
+ for ( i=0; i<distance; i++ )
+    {
+     /* If we encounter a null in either string before we */
+     /* have 'gone the distance' then the strings don't match... */
+
+     if ( ( *s1 == 0 ) || ( *s2 == 0 ) ) return( 0 ); /* No match! */
+
+     ch1 = *s1;
+     ch2 = *s2;
+
+     if ( ( ch1 == '*' ) || ( ch2 == '*' ) )
+       {
+        /* If we are still here and wildcards are allowed */
+        /* then the first one seen in either string causes */
+        /* us to return SUCCESS... */
+
+        if ( haswilds )
+          {
+           return( 1 ); /* Wildcard match was OK this time... */
+          }
+       }
+
+     if ( ch1 == '/' ) ch1 = '\\';
+     if ( ch2 == '/' ) ch2 = '\\';
+
+     if ( ch1 != ch2 ) return( 0 ); /* No match! */
+
+     s1++;
+     s2++;
+
+    }/* End 'i' loop */
+
+ /* If we make it to here then everything MATCHED! */
+
+ return( 1 ); /* MATCH! */
+
+}/* End mod_gzip_ismatch() */
+
+int mod_gzip_get_action_flag( request_rec *r, mod_gzip_conf *mgc )
+{
+    int   x    = 0;
+    int   pass = 0;
+    int   clen = 0;
+    int   hlen = 0;
+    int   flen = 0;
+
+    int   pass_result        = 0;
+    int   filter_value       = 0;
+    int   item_is_included   = 0;
+    int   item_is_excluded   = 0;
+    int   action_flag        = 0;
+    int   this_type          = 0;
+    int   this_action        = 0;
+    char *this_name          = 0;
+    char *file_extension     = 0;
+    int   file_extension_len = 0;
+    char *p1                 = 0;
+
+    #ifdef MOD_GZIP_DEBUG1
+    char cn[]="mod_gzip_get_action_flag()";
+    #endif
+
+    /*
+     * Start...
+     */
+
+    if ( r->content_type ) clen = strlen( r->content_type );
+    if ( r->handler      ) hlen = strlen( r->handler );
+
+    if ( r->filename )
+      {
+       flen = strlen( r->filename );
+       p1   = r->filename;
+       while(*p1!=0){if (*p1=='.') file_extension=p1; p1++;}
+       if ( file_extension ) file_extension_len = strlen( file_extension );
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+
+    mod_gzip_printf( "%s: Entry...\n",cn);
+    mod_gzip_printf( "%s: r->content_type    = [%s]\n",cn,r->content_type);
+    mod_gzip_printf( "%s: clen               = %d\n",  cn,clen);
+    mod_gzip_printf( "%s: r->handler         = [%s]\n",cn,r->handler);
+    mod_gzip_printf( "%s: hlen               = %d\n",  cn,hlen);
+    mod_gzip_printf( "%s: r->filename        = [%s]\n",cn,r->filename);
+    mod_gzip_printf( "%s: flen               = %d\n",  cn,flen);
+    mod_gzip_printf( "%s: file_extension     = [%s]\n",cn,file_extension);
+    mod_gzip_printf( "%s: file_extension_len = %d\n",  cn,file_extension_len);
+
+    #endif /* MOD_GZIP_DEBUG1 */
+
+    /*
+     * Sanity checks...
+     */
+
+    if ( ( hlen == 0 ) && ( clen == 0 ) )
+      {
+       /*
+        * If the header analysis and/or negotiation phase has
+        * determined this to be a CGI script then the r->content_type
+        * field will be (null) but r->handler will contain "cgi-script".
+        * or "php-script" or the like.
+        *
+        * If the analysis has determined this is a static file
+        * then r->handler will be (null) but the r->content_type
+        * field will be "text/html" or "text/plain" or whatever.
+        *
+        * Both the r->content_type field and the r->handler
+        * field are empty. Ignore this one...
+        */
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: Both hlen and clen are ZERO...\n",cn);
+       mod_gzip_printf( "%s: Exit > return( MOD_GZIP_IMAP_DECLINED1 ) >\n",cn);
+       #endif
+
+       if ( r->server->loglevel == APLOG_DEBUG )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "mod_gzip: There is no valid r->handler or r->content_length ");
+         }
+
+       return( MOD_GZIP_IMAP_DECLINED1 );
+      }
+
+    /*
+     * Perform 2 passes at the Include/Exclude list...
+     *
+     * The first  pass is the higher-priority EXCLUSION check.
+     * The second pass is the lower-priority  INCLUSION check.
+     */
+
+    for ( pass=0; pass<2; pass++ )
+    {
+
+    pass_result = 0; /* Reset result */
+
+    if ( pass == 0 ) /* EXCLUSION CHECK */
+      {
+       filter_value = 0;
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: EXCLUSION CHECK...\n",cn);
+       #endif
+      }
+    else if ( pass == 1 ) /* INCLUSION CHECK */
+      {
+       filter_value = 1;
+
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: INCLUSION CHECK...\n",cn);
+       #endif
+      }
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: pass = %d\n", cn, pass );
+    mod_gzip_printf( "%s: filter_value = %d\n", cn, filter_value );
+    mod_gzip_printf( "%s: mgc->imap_total_entries = %d\n", cn,
+                    (int) mgc->imap_total_entries );
+    #endif
+
+    for ( x=0; x<mgc->imap_total_entries; x++ )
+       {
+        if ( r->server->loglevel == APLOG_DEBUG )
+          {
+           /* Show the lookups in the Apache ERROR log if DEBUG is on */
+
+           ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_gzip: mgc->imap[%3.3d] = i%2.2d t%4.4d a%4.4d n[%s]",
+            x,
+            mgc->imap[x].include,
+            mgc->imap[x].type,
+            mgc->imap[x].action,
+            mgc->imap[x].name
+            );
+          }
+
+        #ifdef MOD_GZIP_DEBUG1
+
+        mod_gzip_printf( "%s: --------------------------------------------\n",cn);
+        mod_gzip_printf( "%s: r->handler      = [%s]\n",cn,r->handler);
+        mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
+        mod_gzip_printf( "%s: r->filename     = [%s]\n",cn,r->filename);
+        mod_gzip_printf( "%s: file_extension  = [%s]\n",cn,file_extension);
+        mod_gzip_printf( "%s: mgc->imap[%3.3d].include = %d\n",cn,x,mgc->imap[x].include);
+        mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = %d\n",cn,x,mgc->imap[x].type);
+
+        if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISMIME )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = MOD_GZIP_IMAP_ISMIME\n",cn,x);
+          }
+        else if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISEXT )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = MOD_GZIP_IMAP_ISEXT\n",cn,x);
+          }
+        else if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISHANDLER )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = MOD_GZIP_IMAP_ISHANDLER\n",cn,x);
+          }
+        else /* Unrecognized item type... */
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].type    = MOD_GZIP_IMAP_IS??? Unknown type\n",cn,x);
+          }
+
+        mod_gzip_printf( "%s: mgc->imap[%3.3d].action  = %d\n",  cn,x,mgc->imap[x].action);
+
+        if ( mgc->imap[x].action == MOD_GZIP_IMAP_DYNAMIC1 )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].action  = MOD_GZIP_IMAP_DYNAMIC1\n",cn,x);
+          }
+        else if ( mgc->imap[x].action == MOD_GZIP_IMAP_STATIC1 )
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].action  = MOD_GZIP_IMAP_STATIC1\n",cn,x);
+          }
+        else /* Unrecognized action type... */
+          {
+           mod_gzip_printf( "%s: mgc->imap[%3.3d].action  = MOD_GZIP_IMAP_??? Unknown action\n",cn,x);
+          }
+
+        mod_gzip_printf( "%s: mgc->imap[%3.3d].name    = [%s]\n",cn,x,mgc->imap[x].name);
+
+        #endif /* MOD_GZIP_DEBUG1 */
+
+        /* 'filter_value' mirrors 'pass' value for now but this might */
+        /* not always be true. First pass is EXCLUDE and second is INCLUDE */
+
+        if ( mgc->imap[x].include == filter_value )
+          {
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: This record matches filter_value %d\n",
+                             cn, filter_value );
+           mod_gzip_printf( "%s: The record will be checked...\n",cn);
+           #endif
+
+           /*
+            * Set work values for this record...
+            */
+
+           this_type   = mgc->imap[x].type;
+           this_action = mgc->imap[x].action;
+           this_name   = mgc->imap[x].name;
+
+           /*
+            * If the header analysis and/or negotiation phase has
+            * determined this to be a CGI script then the r->content_type
+            * field will be (null) but r->handler will contain "cgi-script".
+            *
+            * If the analysis has determined this is a static file
+            * then r->handler will be (null) but the r->content_type
+            * field will be "text/html" or "text/plain" or whatever.
+            */
+
+           if ( hlen > 0 ) /* r->handler field has a value... */
+             {
+              #ifdef MOD_GZIP_DEBUG1
+              mod_gzip_printf( "%s: hlen has value...\n",cn);
+              #endif
+
+              if ( this_type == MOD_GZIP_IMAP_ISHANDLER )
+                {
+                 #ifdef MOD_GZIP_DEBUG1
+                 mod_gzip_printf( "%s: this_type = ISHANDLER\n",cn);
+                 mod_gzip_printf( "%s: Call mod_gzip_ismatch(%s,%s,0,0)...\n",
+                                   cn, this_name, r->handler );
+                 #endif
+
+                 /* mod_gzip_ismatch()... */
+
+                 /* The 2 strings must match exactly so  */
+                 /* pass '0' for parm 3...               */
+
+                 /* Wildcard matches are not allowed for */
+                 /* handler strings like 'cgi-script' so */
+                 /* Fourth parm should be 0..            */
+
+                 if ( mod_gzip_ismatch(
+                      this_name, (char *)r->handler,0,0) )
+                   {
+                    pass_result = 1;           /* We found a match */
+                    action_flag = this_action; /* What to do */
+                    break;                     /* Stop now */
+                   }
+
+                }/* End 'if ( this_type == MOD_GZIP_IMAP_ISHANDLER )' */
+
+             }/* End 'if( hlen > 0 )' */
+
+           if ( clen > 0 ) /* r->content_type field has a value... */
+             {
+              #ifdef MOD_GZIP_DEBUG1
+              mod_gzip_printf( "%s: clen has value...\n",cn);
+              #endif
+
+              if ( this_type == MOD_GZIP_IMAP_ISMIME )
+                {
+                 #ifdef MOD_GZIP_DEBUG1
+                 mod_gzip_printf( "%s: this_type = ISMIME\n",cn);
+                 mod_gzip_printf( "%s: Wildcards matches are OK for MIME types.\n",cn);
+                 mod_gzip_printf( "%s: Call mod_gzip_ismatch(%s,%s,0,1)...\n",
+                                   cn, this_name, r->content_type );
+                 #endif
+
+                 /* mod_gzip_ismatch()... */
+
+                 /* Wildcard matches are ALLOWED for    */
+                 /* MIME type strings like 'cgi-script' */
+                 /* so fourth parm should be 1...       */
+
+                 if ( mod_gzip_ismatch(
+                      this_name, (char *)r->content_type, 0, 1 ) )
+                   {
+                    pass_result = 1;           /* We found a match */
+                    action_flag = this_action; /* What to do */
+                    break;                     /* Stop now */
+                   }
+
+                }/* End 'if ( this_type == MOD_GZIP_IMAP_ISMIME )' */
+
+             }/* End 'if( clen > 0 )' */
+
+           if ( flen > 0 ) /* r->filename field has a value... */
+             {
+              #ifdef MOD_GZIP_DEBUG1
+              mod_gzip_printf( "%s: flen has value...\n",cn);
+              #endif
+
+              if ( this_type == MOD_GZIP_IMAP_ISEXT )
+                {
+                 #ifdef MOD_GZIP_DEBUG1
+                 mod_gzip_printf( "%s: this_type = ISEXT\n",cn);
+                 #endif
+
+                 if ( file_extension_len > 0 ) /* There is a file extension */
+                   {
+                    #ifdef MOD_GZIP_DEBUG1
+                    mod_gzip_printf( "%s: file_extension_len has value...\n",cn);
+                    mod_gzip_printf( "%s: Call mod_gzip_ismatch(%s,%s,0,0)...\n",
+                                      cn, this_name, file_extension );
+                    #endif
+
+                    /* mod_gzip_ismatch()... */
+
+                    /* The 2 strings must match exactly so  */
+                    /* pass '0' for parm 3...               */
+
+                    /* Wildcard matches are not allowed for */
+                    /* file extensions like '.html' so      */
+                    /* Fourth parm should be 0..            */
+
+                    if ( mod_gzip_ismatch(
+                         this_name, file_extension, 0, 0 ) )
+                      {
+                       pass_result = 1;           /* We found a match */
+                       action_flag = this_action; /* What to do */
+                       break;                     /* Stop now */
+                      }
+
+                   }/* End 'if( file_extension_len > 0 )' */
+
+                }/* End 'if( this_type == MOD_GZIP)IMAP_ISEXT )' */
+
+             }/* End 'if( flen > 0 )' */
+
+          }/* End 'if ( mgc->imap[x].include == filter )' */
+
+        else /* The record did not match the current 'filter' value... */
+          {
+           #ifdef MOD_GZIP_DEBUG1
+           mod_gzip_printf( "%s: This record does NOT match filter_value %d\n",
+                             cn, filter_value );
+           mod_gzip_printf( "%s: The record has been SKIPPED...\n",cn);
+           #endif
+          }
+
+       }/* End 'x' loop that looks at 'filtered' records... */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: --------------------------------------------\n",cn);
+    mod_gzip_printf( "%s: pass_result = %d\n",cn,pass_result);
+    #endif
+
+    if ( pass_result ) /* We are done... */
+      {
+       if ( pass == 0 ) item_is_excluded = 1;
+       else             item_is_included = 1;
+
+       break; /* Break out of 'pass' loop now... */
+      }
+
+    }/* End 'pass' loop */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: item_is_excluded = %d\n",cn,item_is_excluded);
+    mod_gzip_printf( "%s: item_is_included = %d\n",cn,item_is_included);
+    mod_gzip_printf( "%s: action_flag      = %d\n",cn,action_flag);
+    #endif
+
+    if ( item_is_excluded )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: The item is excluded...\n",cn);
+       mod_gzip_printf( "%s: Exit > return( MOD_GZIP_IMAP_DECLINED1 ) >\n",cn);
+       #endif
+
+       if ( r->server->loglevel == APLOG_DEBUG )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "mod_gzip: This item is EXCLUDED as per httpd.conf");
+         }
+
+       return( MOD_GZIP_IMAP_DECLINED1 );
+      }
+
+    else if ( item_is_included )
+      {
+       #ifdef MOD_GZIP_DEBUG1
+       mod_gzip_printf( "%s: The item is included...\n",cn);
+       mod_gzip_printf( "%s: Exit > return( action_flag = %d ) >\n",cn,action_flag);
+       #endif
+
+       if ( r->server->loglevel == APLOG_DEBUG )
+         {
+          ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+          "mod_gzip: This item is INCLUDED as per httpd.conf");
+         }
+
+       return( action_flag ); /* STATIC1 or DYNAMIC1 */
+      }
+
+    /*
+     * Default action is to DECLINE processing...
+     */
+
+    #ifdef MOD_GZIP_DEBUG1
+    mod_gzip_printf( "%s: Exit > return( MOD_GZIP_IMAP_DECLINED1 ) >\n",cn);
+    #endif
+
+    if ( r->server->loglevel == APLOG_DEBUG )
+      {
+       ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+       "mod_gzip: This item was NOT FOUND in any mod_gzip httpd item record.");
+       ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
+       "mod_gzip: This item will NOT be processed.");
+      }
+
+    return( MOD_GZIP_IMAP_DECLINED1 );
+
+}/* End of mod_gzip_get_action_flag() */
+
+/*--------------------------------------------------------------------------*/
+/* ALL SOURCE CODE BELOW THIS POINT IS COMPRESSION SPECIFIC...              */
+/*--------------------------------------------------------------------------*/
+
+#define USE_GATHER
+extern MODULE_VAR_EXPORT int ap_suexec_enabled;
+extern API_EXPORT(void)
+ap_internal_redirect_handler(const char *new_uri, request_rec *);
+long mod_gzip_ap_send_fb(
+BUFF *fb,
+request_rec *r,
+int *final_return_code
+);
+long mod_gzip_ap_send_fb_length(
+BUFF *fb,
+request_rec *r,
+long length,
+int *final_return_code
+);
+#define DEFAULT_LOGBYTES 10385760
+#define DEFAULT_BUFBYTES 1024
+static int mod_gzip_cgi_child(void *child_stuff, child_info *pinfo);
+typedef struct {
+    char *logname;
+    long logbytes;
+    int bufbytes;
+} cgi_server_conf;
+struct mod_gzip_cgi_child_stuff {
+#ifdef TPF
+    TPF_FORK_CHILD t;
+#endif
+    request_rec *r;
+    int nph;
+    int debug;
+    char *argv0;
+};
+static int is_scriptaliased( request_rec *r )
+{
+ const char *t = ap_table_get(r->notes, "alias-forced-type");
+ return t && (!strcasecmp(t, "cgi-script"));
+}
+static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,
+           int show_errno, char *error)
+{
+    FILE *f;
+    struct stat finfo;
+    ap_log_rerror(APLOG_MARK, show_errno|APLOG_ERR, r, 
+               "%s: %s", error, r->filename);
+    if (!conf->logname ||
+       ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
+        &&   (finfo.st_size > conf->logbytes)) ||
+         ((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname),
+                     "a")) == NULL)) {
+       return ret;
+    }
+    fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
+           r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+    fprintf(f, "%%%% %d %s\n", ret, r->filename);
+    fprintf(f, "%%error\n%s\n", error);
+    ap_pfclose(r->pool, f);
+    return ret;
+}
+static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
+                 char *dbuf, const char *sbuf, BUFF *script_in, BUFF *script_err)
+{
+    array_header *hdrs_arr = ap_table_elts(r->headers_in);
+    table_entry *hdrs = (table_entry *) hdrs_arr->elts;
+    char argsbuffer[HUGE_STRING_LEN];
+    FILE *f;
+    int i;
+    struct stat finfo;
+    if (!conf->logname ||
+       ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
+        &&   (finfo.st_size > conf->logbytes)) ||
+         ((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname),
+                     "a")) == NULL)) {
+       while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
+           continue;
+#if defined(WIN32) || defined(NETWARE)
+        while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, 
+                          "%s", argsbuffer);            
+        }
+#else
+       while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
+           continue;
+#endif
+       return ret;
+    }
+    fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
+           r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+    fprintf(f, "%%%% %d %s\n", ret, r->filename);
+    fputs("%request\n", f);
+    for (i = 0; i < hdrs_arr->nelts; ++i) {
+       if (!hdrs[i].key)
+           continue;
+       fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
+    }
+    if ((r->method_number == M_POST || r->method_number == M_PUT)
+       && *dbuf) {
+       fprintf(f, "\n%s\n", dbuf);
+    }
+    fputs("%response\n", f);
+    hdrs_arr = ap_table_elts(r->err_headers_out);
+    hdrs = (table_entry *) hdrs_arr->elts;
+    for (i = 0; i < hdrs_arr->nelts; ++i) {
+       if (!hdrs[i].key)
+           continue;
+       fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
+    }
+    if (sbuf && *sbuf)
+       fprintf(f, "%s\n", sbuf);
+    if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) {
+       fputs("%stdout\n", f);
+       fputs(argsbuffer, f);
+       while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
+           fputs(argsbuffer, f);
+       fputs("\n", f);
+    }
+    if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
+       fputs("%stderr\n", f);
+       fputs(argsbuffer, f);
+       while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
+           fputs(argsbuffer, f);
+       fputs("\n", f);
+    }
+    ap_bclose( script_in  );
+    ap_bclose( script_err );
+    ap_pfclose(r->pool, f);
+    return ret;
+}
+int mod_gzip_cgi_handler( request_rec *r )
+{
+    int bytesread;
+    int retval, nph, dbpos = 0;
+    char *argv0, *dbuf = NULL;
+    BUFF *script_out, *script_in, *script_err;
+    char argsbuffer[HUGE_STRING_LEN];
+    int is_included = !strcmp(r->protocol, "INCLUDED");
+    void *sconf = r->server->module_config;
+    int final_result = DECLINED;
+    #define MOD_GZIP_ENGAGED
+    #ifdef  MOD_GZIP_ENGAGED
+    cgi_server_conf conf_local;
+    cgi_server_conf *conf = &conf_local;
+    char cgi_logname[]="";
+    #else
+    cgi_server_conf *conf =
+    (cgi_server_conf *) ap_get_module_config(sconf, &cgi_module);
+    #endif
+    const char *location;
+    struct mod_gzip_cgi_child_stuff cld;
+    #ifdef MOD_GZIP_ENGAGED
+    conf->logname  = cgi_logname;
+    conf->logbytes = (long) 60000L;
+    conf->bufbytes = (int)  20000;
+    #endif 
+    if ( r->method_number == M_OPTIONS )
+      {
+       r->allowed |= (1 << M_GET);
+       r->allowed |= (1 << M_POST);
+       return DECLINED;
+      }
+    if ((argv0 = strrchr(r->filename, '/')) != NULL)
+      {
+       argv0++;
+      }
+    else
+      {
+       argv0 = r->filename;
+      }
+    nph = !(strncmp(argv0, "nph-", 4));
+    if ( !(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r) )
+      {
+       return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
+              "Options ExecCGI is off in this directory");
+      }
+    if ( nph && is_included )
+      {
+       return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
+              "attempt to include NPH CGI script");
+      }
+    #if defined(OS2) || defined(WIN32)
+    if ( r->finfo.st_mode == 0 )
+      {
+       struct stat statbuf;
+       char *newfile;
+       newfile = ap_pstrcat(r->pool, r->filename, ".EXE", NULL);
+       if ((stat(newfile, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
+         {
+          return log_scripterror(r, conf, NOT_FOUND, 0,
+                 "script not found or unable to stat");
+         }
+       else 
+         {
+          r->filename = newfile;
+         }
+      }
+    #else 
+    if ( r->finfo.st_mode == 0 )
+      {
+       return log_scripterror(r, conf, NOT_FOUND, APLOG_NOERRNO,
+              "script not found or unable to stat");
+      }
+    #endif 
+    if ( S_ISDIR( r->finfo.st_mode ) )
+      {
+       return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
+              "attempt to invoke directory as script");
+      }
+    if ( !ap_suexec_enabled )
+      {
+       if ( !ap_can_exec( &r->finfo ) )
+         {
+          return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
+                 "file permissions deny server execution");
+         }
+      }
+    if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
+      {
+       return retval;
+      }
+    ap_add_common_vars(r);
+    cld.argv0 = argv0;
+    cld.r     = r;
+    cld.nph   = nph;
+    cld.debug = conf->logname ? 1 : 0;
+    #ifdef TPF
+    cld.t.filename       = r->filename;
+    cld.t.subprocess_env = r->subprocess_env;
+    cld.t.prog_type      = FORK_FILE;
+    #endif 
+    #ifdef CHARSET_EBCDIC
+    ap_bsetflag( r->connection->client, B_EBCDIC2ASCII, 1 );
+    #endif 
+    if ( !ap_bspawn_child(
+          r->main ? r->main->pool : r->pool, 
+          mod_gzip_cgi_child, 
+          (void *) &cld,      
+          kill_after_timeout, 
+          &script_out, 
+          &script_in,  
+          &script_err  
+          )
+       )
+      {
+       ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+       "couldn't spawn child process: %s", r->filename);
+       return HTTP_INTERNAL_SERVER_ERROR;
+      }
+    else 
+      {
+      }
+    if ( ap_should_client_block(r) )
+      {
+       int dbsize, len_read;
+       if ( conf->logname )
+         {
+          dbuf  = ap_pcalloc( r->pool, conf->bufbytes + 1 );
+          dbpos = 0; 
+         }
+       ap_hard_timeout("copy script args", r);
+       for (;;)
+          {
+           len_read =
+           ap_get_client_block( r, argsbuffer, HUGE_STRING_LEN );
+           if ( len_read < 1 ) 
+             {
+              break; 
+             }
+           if (conf->logname)
+             {
+              if ((dbpos + len_read) > conf->bufbytes)
+                {
+                 dbsize = conf->bufbytes - dbpos;
+                }
+              else
+                {
+                 dbsize = len_read;
+                }
+              memcpy(dbuf + dbpos, argsbuffer, dbsize);
+              dbpos += dbsize;
+             }
+           ap_reset_timeout(r);
+           if ( ap_bwrite(script_out, argsbuffer, len_read) < len_read )
+             {
+              while ( len_read=
+                      ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0)
+                {
+                }
+              break;
+             }
+           else 
+             {
+             }
+          }
+       ap_bflush( script_out );
+       ap_kill_timeout(r);
+      }
+    else 
+      {
+      }
+    ap_bclose( script_out );
+    if ( script_in && !nph )
+      {
+       char sbuf[MAX_STRING_LEN];
+       int ret;
+       if ((ret = ap_scan_script_header_err_buff(r, script_in, sbuf)))
+         {
+          return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err);
+         }
+       #ifdef CHARSET_EBCDIC
+       ap_checkconv(r);
+       #endif 
+       location = ap_table_get( r->headers_out, "Location" );
+       if ( location && location[0] == '/' && r->status == 200 )
+         {
+          ap_hard_timeout("read from script", r);
+          while ( ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0 )
+            {
+             continue;
+            }
+          while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
+            {
+             continue;
+            }
+          ap_kill_timeout(r);
+          r->method = ap_pstrdup(r->pool, "GET");
+          r->method_number = M_GET;
+          ap_table_unset( r->headers_in, "Content-Length" );
+          ap_internal_redirect_handler( location, r );
+          return OK;
+         }
+       else if ( location && r->status == 200 )
+         {
+          return REDIRECT;
+         }
+       #ifdef USE_GATHER
+       if ( r->header_only )
+         {
+          ap_send_http_header(r);
+         }
+       else
+         {
+         }
+       #else /* !USE_GATHER */
+       ap_send_http_header(r);
+       #endif /* USE_GATHER */
+       if (!r->header_only)
+         {
+          mod_gzip_ap_send_fb( script_in, r, &final_result );
+         }
+       ap_bclose( script_in );
+       ap_soft_timeout("soaking script stderr", r);
+       for (;;)
+          {
+           bytesread = ap_bgets( argsbuffer, HUGE_STRING_LEN, script_err );
+           if ( bytesread < 1 )
+             {
+              break;
+             }
+          }
+       ap_kill_timeout(r);
+       ap_bclose( script_err );
+      }
+    else 
+      {
+      }
+    if ( script_in && nph )
+      {
+       #ifdef RUSSIAN_APACHE
+       if (ra_charset_active(r))
+         {
+          r->ra_codep=NULL;
+         }
+       #endif 
+       mod_gzip_ap_send_fb( script_in, r, &final_result );
+      }
+    else 
+      {
+      }
+    #ifdef ORIGINAL
+    return OK; 
+    #endif
+    return final_result;
+}
+static int mod_gzip_cgi_child(void *child_stuff, child_info *pinfo)
+{
+    struct mod_gzip_cgi_child_stuff *cld = (struct mod_gzip_cgi_child_stuff *) child_stuff;
+    request_rec *r = cld->r;
+    char *argv0 = cld->argv0;
+    int child_pid;
+
+/* WARNING! If the following DEBUG_CGI switch is ON you may need to */
+/* run Apache with the -X switch or the dynamic compression */
+/* of some CGI output ( most notable Zope ) will start to fail. */
+/* This DEBUG_CGI switch should NEVER be on for production runs. */
+/*
+#define DEBUG_CGI
+*/
+
+#ifdef DEBUG_CGI
+#ifdef OS2
+    FILE *dbg = fopen("con", "w");
+#else
+    #ifdef WIN32
+    FILE *dbg = fopen("c:\\script.dbg", "a" );
+    #else
+    FILE *dbg = fopen("/dev/tty", "w");
+    #endif
+#endif
+    int i;
+#endif
+    char **env;
+    RAISE_SIGSTOP(CGI_CHILD);
+#ifdef DEBUG_CGI
+    fprintf(dbg, "Attempting to exec %s as %sCGI child (argv0 = %s)\n",
+           r->filename, cld->nph ? "NPH " : "", argv0);
+#endif
+    ap_add_cgi_vars(r);
+    env = ap_create_environment(r->pool, r->subprocess_env);
+#ifdef DEBUG_CGI
+    fprintf(dbg, "Environment: \n");
+    for (i = 0; env[i]; ++i)
+       fprintf(dbg, "'%s'\n", env[i]);
+#endif
+#ifndef WIN32
+    #ifdef DEBUG_CGI
+    fprintf(dbg, "Call ap_chdir_file(r->filename=[%s]\n",r->filename);
+    #endif
+    ap_chdir_file(r->filename);
+    #ifdef DEBUG_CGI
+    fprintf(dbg, "Back ap_chdir_file(r->filename=[%s]\n",r->filename);
+    #endif
+#endif
+    if (!cld->debug)
+       ap_error_log2stderr(r->server);
+#ifdef TPF
+    #ifdef DEBUG_CGI
+    #ifdef WIN32
+    fprintf(dbg, "TPF defined... return( 0 ) now...\n");
+    if ( dbg ) { fclose(dbg); dbg=0; }
+    #endif
+    #endif
+    return (0);
+#else
+    #ifdef DEBUG_CGI
+    fprintf(dbg, "Call ap_cleanup_for_exec()...\n");
+    #endif
+    ap_cleanup_for_exec();
+    #ifdef DEBUG_CGI
+    fprintf(dbg, "Back ap_cleanup_for_exec()...\n");
+    fprintf(dbg, "Call ap_call_exec()...\n");
+    #endif
+    child_pid = ap_call_exec(r, pinfo, argv0, env, 0);
+    #ifdef DEBUG_CGI
+    fprintf(dbg, "Back ap_call_exec()...\n");
+    #endif
+#if defined(WIN32) || defined(OS2)
+    #ifdef DEBUG_CGI
+    #ifdef WIN32
+    fprintf(dbg, "WIN32 or OS2 defined... return( child_pid ) now...\n");
+    if ( dbg ) { fclose(dbg); dbg=0; }
+    #endif
+    #endif
+    return (child_pid);
+#else
+    ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "exec of %s failed", r->filename);
+    exit(0);
+    #ifdef DEBUG_CGI
+    #ifdef WIN32
+    if ( dbg ) { fclose(dbg); dbg=0; }
+    #endif
+    #endif
+    return (0);
+#endif
+#endif  
+}
+#define MOD_GZIP_SET_BYTES_SENT(r) \
+  do { if (r->sent_bodyct) \
+          ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
+  } while (0)
+long mod_gzip_ap_send_fb( BUFF *fb, request_rec *r, int *final_return_code )
+{
+ long lrc;
+ int  return_code=DECLINED;
+ lrc = (long ) mod_gzip_ap_send_fb_length( fb, r, -1, &return_code );
+ *final_return_code = return_code;
+ return lrc;
+}
+#ifdef USE_TPF_SELECT
+#define mod_gzip_ap_select(_a, _b, _c, _d, _e)   \
+       tpf_select(_a, _b, _c, _d, _e)
+#elif defined(SELECT_NEEDS_CAST)
+#define mod_gzip_ap_select(_a, _b, _c, _d, _e)   \
+    select((_a), (int *)(_b), (int *)(_c), (int *)(_d), (_e))
+#else
+#define mod_gzip_ap_select(_a, _b, _c, _d, _e)   \
+       select(_a, _b, _c, _d, _e)
+#endif
+long mod_gzip_ap_send_fb_length(
+BUFF *fb,
+request_rec *r,
+long length,
+int *final_return_code
+)
+{
+    char cn[]="mod_gzip_ab_send_fb_length()";
+    char buf[IOBUFSIZE];
+    long total_bytes_sent = 0;
+    register int n;
+    register int len;
+    register int fd;
+    fd_set   fds;
+    int      rc;
+    #ifndef  USE_GATHER
+    register int w;
+    register int o;
+    #endif
+    #ifdef USE_GATHER
+    int   gather_on           = 0;
+    int   gather_todisk       = 0;
+    int   gather_origin       = 0;
+    char *gather_bufstart     = 0;
+    char *gather_source       = 0;
+    char *gather_buf          = 0;
+    int   gather_bufmaxlen    = 60000; 
+    int   gather_byteswritten = 0;
+    int   gather_length       = 0;
+    int   gather_maxlen       = 0;
+    long  gather_totlen       = 0; 
+    FILE *gather_fh1          = 0;
+    char  gather_filename[ MOD_GZIP_MAX_PATH_LEN + 2 ];
+    #endif 
+    void *modconf = r->server->module_config;
+    mod_gzip_conf *conf;
+    *final_return_code = DECLINED; 
+    conf = (mod_gzip_conf *) ap_get_module_config( modconf, &gzip_module );
+    if ( length == 0 )
+      {
+       return 0;
+      }
+    ap_bsetflag( fb, B_RD, 0 );
+    #ifndef TPF
+    ap_bnonblock( fb, B_RD );
+    #endif 
+    fd = ap_bfileno( fb, B_RD );
+    #ifdef CHECK_FD_SETSIZE
+    if ( fd >= FD_SETSIZE )
+      {
+       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
+       "send body: filedescriptor (%u) larger than FD_SETSIZE (%u) "
+       "found, you probably need to rebuild Apache with a "
+       "larger FD_SETSIZE", fd, FD_SETSIZE);
+       return 0;
+      }
+    else 
+      {
+      }
+    #else 
+    #endif 
+    ap_soft_timeout("send body", r);
+    FD_ZERO( &fds );
+    #ifdef USE_GATHER
+    gather_on = 0; 
+    if ( (long) conf->maximum_inmem_size < (long) gather_bufmaxlen )
+      {
+       gather_maxlen = (int) conf->maximum_inmem_size;
+      }
+    else
+      {
+       gather_maxlen = (int) gather_bufmaxlen;
+      }
+    gather_bufstart = malloc( (int)(gather_maxlen + 2) );
+    if ( gather_bufstart )
+      {
+       gather_on     = 1; 
+       gather_buf    = gather_bufstart;  
+       gather_source = gather_bufstart;  
+       gather_origin = 0;                
+      }
+    else 
+      {
+      }
+    #endif 
+    while( !r->connection->aborted )
+      {
+       #ifdef NDELAY_PIPE_RETURNS_ZERO
+       int afterselect = 0;
+       #endif
+       if ( (length > 0) && (total_bytes_sent + IOBUFSIZE) > length )
+         {
+          len = length - total_bytes_sent;
+         }
+       else
+         {
+          len = IOBUFSIZE;
+         }
+       do {
+           n = ap_bread( fb, buf, len );
+           #ifdef NDELAY_PIPE_RETURNS_ZERO
+           if ((n > 0) || (n == 0 && afterselect))
+             {
+              break;
+             }
+           #else 
+           if (n >= 0)
+             {
+              break;
+             }
+           #endif 
+           if ( r->connection->aborted )
+             {
+              break;
+             }
+           if ( n < 0 && errno != EAGAIN )
+             {
+              break;
+             }
+           if ( ap_bflush( r->connection->client ) < 0 )
+             {
+              ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+              "client stopped connection before send body completed");
+              ap_bsetflag( r->connection->client, B_EOUT, 1 );
+              r->connection->aborted = 1; 
+              break; 
+             }
+           #ifdef WIN32
+           FD_SET( (unsigned) fd, &fds );
+           #else
+           FD_SET( fd, &fds );
+           #endif
+           #ifdef FUTURE_USE
+           mod_gzip_ap_select(fd + 1, &fds, NULL, NULL, NULL);
+           #endif
+           #ifdef NDELAY_PIPE_RETURNS_ZERO
+           afterselect = 1;
+           #endif
+          } while ( !r->connection->aborted );
+       if ( n < 1 || r->connection->aborted )
+         {
+          break; 
+         }
+       #ifdef USE_GATHER
+       if ( gather_on )
+         {
+          if ( ( gather_length + n ) >= gather_maxlen )
+            {
+             if ( !gather_fh1 ) 
+               {
+                mod_gzip_create_unique_filename(
+                (mod_gzip_conf *) conf,
+                (char *) gather_filename,
+                sizeof(  gather_filename )
+                );
+                gather_fh1 = fopen( gather_filename, "wb" );
+                if ( gather_fh1 )
+                  {
+                   gather_source = gather_filename; 
+                   gather_origin = 1;               
+                  }
+                else
+                  {
+                   gather_on = 0; 
+                  }
+               }
+             if ( ( gather_fh1 ) && ( gather_length > 0 ) )
+               {
+                gather_byteswritten =
+                fwrite( gather_bufstart, 1, gather_length, gather_fh1 );
+                if ( gather_byteswritten != gather_length )
+                  {
+                   gather_on = 0; 
+                  }
+               }
+             if ( ( gather_fh1 ) && ( n > 0 ) )
+               {
+                gather_byteswritten =
+                fwrite( buf, 1, n, gather_fh1 );
+                if ( gather_byteswritten != n )
+                  {
+                   gather_on = 0; 
+                  }
+               }
+             gather_buf    = gather_bufstart;
+             gather_length = 0;
+            }
+          else 
+            {
+             if ( gather_on )
+               {
+                memcpy( gather_buf, buf, n );
+                gather_buf    += n; 
+                gather_length += n; 
+               }
+            }
+          gather_totlen += n; 
+         }
+       #endif 
+       #ifdef FUTURE_USE
+       o = 0;
+       while ( n && !r->connection->aborted )
+         {
+          #ifdef RUSSIAN_APACHE
+          unsigned char *newbuf,*p;
+          int newlen=0;
+          if ( ra_charset_active(r) )
+            {
+             if ( ra_flag( r, RA_WIDE_CHARS_SC ) )
+               {
+                ra_data_server2client(r,&buf[o],n,&newbuf,&newlen);
+                p=newbuf;
+                while( newlen > 0 )
+                  {
+                   w = ap_bwrite( r->connection->client, p, newlen );
+                   if(w<=0) goto RECODE_DONE;
+                   newlen-=w;
+                   p+=w;
+                  }
+                w=n;
+               }
+             else 
+               {
+                unsigned char *t   = r->ra_codep->cp_otabl_p;
+                unsigned char *b   = (unsigned char *)&buf[o];
+                unsigned char *end = b+n;
+                while( b < end )
+                  {
+                   *b = t[*b];
+                   b++;
+                  }
+                w = ap_bwrite( r->connection->client, &buf[o], n );
+               }
+            }
+          else 
+            {
+             w = ap_bwrite( r->connection->client, &buf[o], n );
+            }
+          RECODE_DONE:; 
+          #else 
+          w = ap_bwrite( r->connection->client, &buf[o], n );
+          #endif 
+          if ( w > 0 ) 
+            {
+             ap_reset_timeout(r);
+             total_bytes_sent += w;
+             n -= w;
+             o += w;
+            }
+          else if ( w < 0 ) 
+            {
+             if ( !r->connection->aborted )
+               {
+                ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
+                "client stopped connection before send body completed");
+                ap_bsetflag(r->connection->client, B_EOUT, 1);
+                r->connection->aborted = 1;
+               }
+             break;
+            }
+         }
+       #endif 
+      }
+    ap_kill_timeout(r);
+    MOD_GZIP_SET_BYTES_SENT(r); 
+    #ifdef USE_GATHER
+    if ( gather_fh1 ) 
+      {
+       if ( gather_length > 0 )
+         {
+          gather_byteswritten =
+          fwrite( gather_bufstart, 1, gather_length, gather_fh1 );
+          if ( gather_byteswritten != gather_length )
+            {
+             gather_on = 0; 
+            }
+         }
+       fclose( gather_fh1 );
+               gather_fh1 = 0;
+      }
+    if ( gather_totlen > 0 )
+      {
+       rc =
+       mod_gzip_encode_and_transmit(
+       (request_rec *) r,               
+       (char        *) gather_source,   
+       (int          ) gather_origin,   
+       (long         ) gather_totlen,
+       (int          ) 1 
+       );
+       *final_return_code = rc;
+      }
+    if ( gather_bufstart ) 
+      {
+       free( gather_bufstart );
+             gather_bufstart = 0;
+      }
+    gather_on = 0; 
+    #endif 
+    return total_bytes_sent;
+}
+
+/*--------------------------------------------------------------------------*/
+/* COMPRESSION SUPPORT ROUTINES                                             */
+/*--------------------------------------------------------------------------*/
+
+#define BIG_MEM
+
+typedef unsigned       uns;
+typedef unsigned int   uni;
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+typedef int            gz1_file_t;
+
+#ifdef __STDC__
+   typedef void *voidp;
+#else
+   typedef char *voidp;
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+
+#if defined(__OS2__) && !defined(OS2)
+#  define OS2
+#endif
+
+#if defined(OS2) && defined(MSDOS)
+#  undef MSDOS
+#endif
+
+#ifdef MSDOS
+#  ifdef __GNUC__
+#    define near
+#  else
+#    define MAXSEG_64K
+#    ifdef __TURBOC__
+#      define NO_OFF_T
+#      ifdef __BORLANDC__
+#        define DIRENT
+#      else
+#        define NO_UTIME
+#      endif
+#    else
+#      define HAVE_SYS_UTIME_H
+#      define NO_UTIME_H
+#    endif
+#  endif
+#  define PATH_SEP2 '\\'
+#  define PATH_SEP3 ':'
+#  define MAX_PATH_LEN  128
+#  define NO_MULTIPLE_DOTS
+#  define MAX_EXT_CHARS 3
+#  define Z_SUFFIX "z"
+#  define NO_CHOWN
+#  define PROTO
+#  define STDC_HEADERS
+#  define NO_SIZE_CHECK
+#  define casemap(c) tolow(c)
+#  include <io.h>
+#  undef  OS_CODE
+#  define OS_CODE  0x00
+#  define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+#  if !defined(NO_ASM) && !defined(ASMV)
+#    define ASMV
+#  endif
+#else
+#  define near
+#endif
+
+#ifdef OS2
+#  define PATH_SEP2 '\\'
+#  define PATH_SEP3 ':'
+#  define MAX_PATH_LEN  260
+#  ifdef OS2FAT
+#    define NO_MULTIPLE_DOTS
+#    define MAX_EXT_CHARS 3
+#    define Z_SUFFIX "z"
+#    define casemap(c) tolow(c)
+#  endif
+#  define NO_CHOWN
+#  define PROTO
+#  define STDC_HEADERS
+#  include <io.h>
+#  undef  OS_CODE
+#  define OS_CODE  0x06
+#  define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+#  ifdef _MSC_VER
+#    define HAVE_SYS_UTIME_H
+#    define NO_UTIME_H
+#    define MAXSEG_64K
+#    undef near
+#    define near _near
+#  endif
+#  ifdef __EMX__
+#    define HAVE_SYS_UTIME_H
+#    define NO_UTIME_H
+#    define DIRENT
+#    define EXPAND(argc,argv) \
+       {_response(&argc, &argv); _wildcard(&argc, &argv);}
+#  endif
+#  ifdef __BORLANDC__
+#    define DIRENT
+#  endif
+#  ifdef __ZTC__
+#    define NO_DIR
+#    define NO_UTIME_H
+#    include <dos.h>
+#    define EXPAND(argc,argv) \
+       {response_expand(&argc, &argv);}
+#  endif
+#endif
+
+#ifdef WIN32
+#  define HAVE_SYS_UTIME_H
+#  define NO_UTIME_H
+#  define PATH_SEP2 '\\'
+#  define PATH_SEP3 ':'
+#  undef  MAX_PATH_LEN
+#  define MAX_PATH_LEN  260
+#  define NO_CHOWN
+#  define PROTO
+#  define STDC_HEADERS
+#  define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+#  include <io.h>
+#  ifdef NTFAT
+#    define NO_MULTIPLE_DOTS
+#    define MAX_EXT_CHARS 3
+#    define Z_SUFFIX "z"
+#    define casemap(c) tolow(c)
+#  endif
+#  undef  OS_CODE
+
+#  define OS_CODE  0x00
+
+#endif
+
+#ifdef MSDOS
+#  ifdef __TURBOC__
+#    include <alloc.h>
+#    define DYN_ALLOC
+     void * fcalloc (unsigned items, unsigned size);
+     void fcfree (void *ptr);
+#  else
+#    define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
+#    define fcfree(ptr) hfree(ptr)
+#  endif
+#else
+#  ifdef MAXSEG_64K
+#    define fcalloc(items,size) calloc((items),(size))
+#  else
+#    define fcalloc(items,size) malloc((size_t)(items)*(size_t)(size))
+#  endif
+#  define fcfree(ptr) free(ptr)
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define PATH_SEP ']'
+#  define PATH_SEP2 ':'
+#  define SUFFIX_SEP ';'
+#  define NO_MULTIPLE_DOTS
+#  define Z_SUFFIX "-gz"
+#  define RECORD_IO 1
+#  define casemap(c) tolow(c)
+#  undef  OS_CODE
+#  define OS_CODE  0x02
+#  define OPTIONS_VAR "GZIP_OPT"
+#  define STDC_HEADERS
+#  define NO_UTIME
+#  define EXPAND(argc,argv) vms_expand_args(&argc,&argv);
+#  include <file.h>
+#  define unlink delete
+#  ifdef VAXC
+#    define NO_FCNTL_H
+#    include <unixio.h>
+#  endif
+#endif
+
+#ifdef AMIGA
+#  define PATH_SEP2 ':'
+#  define STDC_HEADERS
+#  undef  OS_CODE
+#  define OS_CODE  0x01
+#  define ASMV
+#  ifdef __GNUC__
+#    define DIRENT
+#    define HAVE_UNISTD_H
+#  else
+#    define NO_STDIN_FSTAT
+#    define SYSDIR
+#    define NO_SYMLINK
+#    define NO_CHOWN
+#    define NO_FCNTL_H
+#    include <fcntl.h>
+#    define direct dirent
+     extern void _expand_args(int *argc, char ***argv);
+#    define EXPAND(argc,argv) _expand_args(&argc,&argv);
+#    undef  O_BINARY
+#  endif
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  ifndef STDC_HEADERS
+#    define STDC_HEADERS
+#    define HAVE_UNISTD_H
+#    define DIRENT
+#  endif
+#  define ASMV
+#  undef  OS_CODE
+#  define OS_CODE  0x05
+#  ifdef TOSFS
+#    define PATH_SEP2 '\\'
+#    define PATH_SEP3 ':'
+#    define MAX_PATH_LEN  128
+#    define NO_MULTIPLE_DOTS
+#    define MAX_EXT_CHARS 3
+#    define Z_SUFFIX "z"
+#    define NO_CHOWN
+#    define casemap(c) tolow(c)
+#    define NO_SYMLINK
+#  endif
+#endif
+
+#ifdef MACOS
+#  define PATH_SEP ':'
+#  define DYN_ALLOC
+#  define PROTO
+#  define NO_STDIN_FSTAT
+#  define NO_CHOWN
+#  define NO_UTIME
+#  define chmod(file, mode) (0)
+#  define OPEN(name, flags, mode) open(name, flags)
+#  undef  OS_CODE
+#  define OS_CODE  0x07
+#  ifdef MPW
+#    define isatty(fd) ((fd) <= 2)
+#  endif
+#endif
+
+#ifdef __50SERIES
+#  define PATH_SEP '>'
+#  define STDC_HEADERS
+#  define NO_MEMORY_H
+#  define NO_UTIME_H
+#  define NO_UTIME
+#  define NO_CHOWN 
+#  define NO_STDIN_FSTAT 
+#  define NO_SIZE_CHECK 
+#  define NO_SYMLINK
+#  define RECORD_IO  1
+#  define casemap(c)  tolow(c)
+#  define put_char(c) put_byte((c) & 0x7F)
+#  define get_char(c) ascii2pascii(get_byte())
+#  undef  OS_CODE
+#  define OS_CODE  0x0F
+#  ifdef SIGTERM
+#    undef SIGTERM
+#  endif
+#endif
+
+#if defined(pyr) && !defined(NOMEMCPY)
+#  define NOMEMCPY
+#endif
+
+#ifdef TOPS20
+#  undef  OS_CODE
+#  define OS_CODE  0x0a
+#endif
+
+#ifndef unix
+#  define NO_ST_INO
+#endif
+
+#ifndef OS_CODE
+#  undef  OS_CODE
+#  define OS_CODE  0x03
+#endif
+
+#ifndef PATH_SEP
+#  define PATH_SEP '/'
+#endif
+
+#ifndef casemap
+#  define casemap(c) (c)
+#endif
+
+#ifndef OPTIONS_VAR
+#  define OPTIONS_VAR "GZIP"
+#endif
+
+#ifndef Z_SUFFIX
+#  define Z_SUFFIX ".gz"
+#endif
+
+#ifdef MAX_EXT_CHARS
+#  define MAX_SUFFIX  MAX_EXT_CHARS
+#else
+#  define MAX_SUFFIX  30
+#endif
+
+#ifndef MIN_PART
+#  define MIN_PART 3
+#endif
+
+#ifndef EXPAND
+#  define EXPAND(argc,argv)
+#endif
+
+#ifndef RECORD_IO
+#  define RECORD_IO 0
+#endif
+
+#ifndef SET_BINARY_MODE
+#  define SET_BINARY_MODE(fd)
+#endif
+
+#ifndef OPEN
+#  define OPEN(name, flags, mode) open(name, flags, mode)
+#endif
+
+#ifndef get_char
+#  define get_char() get_byte()
+#endif
+
+#ifndef put_char
+#  define put_char(c) put_byte(c)
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define OK          0
+#define LZ1_ERROR   1
+#define WARNING     2
+#define STORED      0
+#define COMPRESSED  1
+#define PACKED      2
+#define LZHED       3
+#define DEFLATED    8
+#define MAX_METHODS 9
+
+#ifndef O_CREAT
+#include <sys/file.h>
+#ifndef O_CREAT
+#define O_CREAT FCREAT
+#endif
+#ifndef O_EXCL
+#define O_EXCL FEXCL
+#endif
+#endif
+
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 0200
+#endif
+#define RW_USER (S_IRUSR | S_IWUSR)
+
+#ifndef MAX_PATH_LEN
+#define MAX_PATH_LEN 256
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#define PACK_MAGIC     "\037\036"
+#define GZIP_MAGIC     "\037\213"
+#define OLD_GZIP_MAGIC "\037\236"
+#define LZH_MAGIC      "\037\240"
+#define PKZIP_MAGIC    "\120\113\003\004"
+#define ASCII_FLAG   0x01 
+#define CONTINUATION 0x02 
+#define EXTRA_FIELD  0x04 
+#define ORIG_NAME    0x08 
+#define COMMENT      0x10 
+#define ENCRYPTED    0x20 
+#define RESERVED     0xC0 
+#define UNKNOWN 0xffff
+#define BINARY  0
+#define ASCII   1
+
+#ifndef WSIZE
+#define WSIZE 0x8000
+#endif
+
+#ifndef INBUFSIZ
+#ifdef  SMALL_MEM
+#define INBUFSIZ  0x2000
+#else
+#define INBUFSIZ  0x8000
+#endif
+#endif
+#define INBUF_EXTRA 64
+
+#ifndef        OUTBUFSIZ
+#ifdef SMALL_MEM
+#define OUTBUFSIZ   8192
+#else
+#define OUTBUFSIZ  0x4000
+#endif
+#endif
+#define OUTBUF_EXTRA 2048
+
+#ifndef DIST_BUFSIZE
+#ifdef  SMALL_MEM
+#define DIST_BUFSIZE 0x2000
+#else
+#define DIST_BUFSIZE 0x8000
+#endif
+#endif
+
+#ifndef BITS
+#define BITS 16
+#endif
+
+#define LZW_MAGIC  "\037\235"
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)
+
+#ifdef  SMALL_MEM
+#define HASH_BITS  13
+#endif
+#ifdef  MEDIUM_MEM
+#define HASH_BITS  14
+#endif
+#ifndef HASH_BITS
+#define HASH_BITS  15
+#endif
+
+#define HASH_SIZE (unsigned)(1<<HASH_BITS)
+#define HASH_MASK (HASH_SIZE-1)
+#define WMASK     (WSIZE-1)
+#define H_SHIFT   ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
+
+#ifndef TOO_FAR
+#define TOO_FAR 4096
+#endif
+
+#define NIL          0
+#define FAST         4
+#define SLOW         2
+#define REP_3_6      16
+#define REPZ_3_10    17
+#define REPZ_11_138  18
+#define MAX_BITS     15
+#define MAX_BL_BITS  7
+#define D_CODES      30
+#define BL_CODES     19
+#define SMALLEST     1
+#define LENGTH_CODES 29
+#define LITERALS     256
+#define END_BLOCK    256
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+
+#ifndef LIT_BUFSIZE
+#ifdef  SMALL_MEM
+#define LIT_BUFSIZE  0x2000
+#else
+#ifdef  MEDIUM_MEM
+#define LIT_BUFSIZE  0x4000
+#else
+#define LIT_BUFSIZE  0x8000
+#endif
+#endif
+#endif
+
+#define HEAP_SIZE (2*L_CODES+1)
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+#define NO_FILE  (-1) 
+
+#define BMAX 16         
+#define N_MAX 288       
+
+#define LOCSIG 0x04034b50L      
+#define LOCFLG 6                
+#define CRPFLG 1                
+#define EXTFLG 8                
+#define LOCHOW 8                
+#define LOCTIM 10               
+#define LOCCRC 14               
+#define LOCSIZ 18               
+#define LOCLEN 22               
+#define LOCFIL 26               
+#define LOCEXT 28               
+#define LOCHDR 30               
+#define EXTHDR 16               
+#define RAND_HEAD_LEN  12
+#define BUFSIZE (8 * 2*sizeof(char))
+
+#define translate_eol 0  
+
+#define FLUSH_BLOCK(eof) \
+   flush_block(gz1,gz1->block_start >= 0L ? (char*)&gz1->window[(unsigned)gz1->block_start] : \
+         (char*)NULL, (long)gz1->strstart - gz1->block_start, (eof))
+
+#ifdef DYN_ALLOC
+#  define ALLOC(type, array, size) { \
+      array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
+      if (array == NULL) error("insufficient memory"); \
+   }
+#  define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
+#else
+#  define ALLOC(type, array, size)
+#  define FREE(array)
+#endif
+
+#define GZ1_MAX(a,b) (a >= b ? a : b)
+
+#define tolow(c)  (isupper(c) ? (c)-'A'+'a' : (c))    
+
+#define smaller(tree, n, m) \
+   (tree[n].fc.freq < tree[m].fc.freq || \
+   (tree[n].fc.freq == tree[m].fc.freq && gz1->depth[n] <= gz1->depth[m]))
+
+#define send_code(c, tree) send_bits(gz1,tree[c].fc.code, tree[c].dl.len)
+
+#define put_byte(c) {gz1->outbuf[gz1->outcnt++]=(uch)(c); if (gz1->outcnt==OUTBUFSIZ)\
+                     flush_outbuf(gz1);}
+
+#define put_short(w) \
+{ if (gz1->outcnt < OUTBUFSIZ-2) { \
+    gz1->outbuf[gz1->outcnt++] = (uch) ((w) & 0xff); \
+    gz1->outbuf[gz1->outcnt++] = (uch) ((ush)(w) >> 8); \
+  } else { \
+    put_byte((uch)((w) & 0xff)); \
+    put_byte((uch)((ush)(w) >> 8)); \
+  } \
+}
+
+#define put_long(n) { \
+    put_short((n) & 0xffff); \
+    put_short(((ulg)(n)) >> 16); \
+}
+
+#ifdef CRYPT
+
+#  define NEXTBYTE() \
+     (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
+#else
+#  define NEXTBYTE() (uch)get_byte()
+#endif
+
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+#define put_ubyte(c) {gz1->window[gz1->outcnt++]=(uch)(c); if (gz1->outcnt==WSIZE)\
+   flush_window(gz1);}
+
+#define WARN(msg) { if (gz1->exit_code == OK) gz1->exit_code = WARNING; }
+
+#define get_byte()  (gz1->inptr < gz1->insize ? gz1->inbuf[gz1->inptr++] : fill_inbuf(gz1,0))
+#define try_byte()  (gz1->inptr < gz1->insize ? gz1->inbuf[gz1->inptr++] : fill_inbuf(gz1,1))
+
+#define d_code(dist) \
+   ((dist) < 256 ? gz1->dist_code[dist] : gz1->dist_code[256+((dist)>>7)])
+
+typedef struct config {
+   ush good_length; 
+   ush max_lazy;    
+   ush nice_length; 
+   ush max_chain;
+} config;
+
+config configuration_table[10] = {
+
+ {0,    0,  0,    0},  
+ {4,    4,  8,    4},  
+ {4,    5, 16,    8},
+ {4,    6, 32,   32},
+ {4,    4, 16,   16},  
+ {8,   16, 32,   32},
+ {8,   16, 128, 128},
+ {8,   32, 128, 256},
+ {32, 128, 258, 1024},
+ {32, 258, 258, 4096}}; 
+
+typedef struct ct_data {
+
+    union {
+        ush  freq; 
+        ush  code; 
+    } fc;
+    union {
+        ush  dad;  
+        ush  len;  
+    } dl;
+
+} ct_data;
+
+typedef struct tree_desc {
+    ct_data *dyn_tree;    
+    ct_data *static_tree; 
+    int     *extra_bits;  
+    int     extra_base;   
+    int     elems;        
+    int     max_length;   
+    int     max_code;     
+} tree_desc;
+
+struct huft {
+  uch e;                
+  uch b;                
+  union {
+    ush n;              
+    struct huft *t;     
+  } v;
+};
+
+uch bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+int extra_lbits[LENGTH_CODES]
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+int extra_dbits[D_CODES]
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+int extra_blbits[BL_CODES]
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+ulg crc_32_tab[] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+
+typedef struct _GZ1 {
+ long     compression_format;
+
+ long     versionid1;
+ int      state;
+ int      done;
+ int      deflate1_initialized;     
+ unsigned deflate1_hash_head;       
+ unsigned deflate1_prev_match;      
+ int      deflate1_flush;           
+ int      deflate1_match_available; 
+ unsigned deflate1_match_length;    
+
+ char ifname[MAX_PATH_LEN]; 
+ char ofname[MAX_PATH_LEN]; 
+
+ struct stat istat;     
+ gz1_file_t  zfile;
+ int   input_ismem;     
+ char *input_ptr;       
+ long  input_bytesleft; 
+ int   output_ismem;    
+ char *output_ptr;      
+ uns   output_maxlen;   
+
+ int  compr_level;      
+ long time_stamp;       
+ long ifile_size;       
+ int  ifd;              
+ int  ofd;              
+ int  part_nb;          
+ int  last_member;      
+ int  save_orig_name;   
+ long header_bytes;     
+ long bytes_in;         
+ long bytes_out;        
+ uns  insize;           
+ uns  inptr;            
+ uns  outcnt;           
+ uns  ins_h;            
+ long block_start;      
+ uns  good_match;       
+ uni  max_lazy_match;   
+ uni  prev_length;      
+ uns  max_chain_length; 
+ uns  strstart;         
+ uns  match_start;      
+ int  eofile;           
+ uns  lookahead;        
+ ush *file_type;        
+ int *file_method;      
+ ulg  opt_len;          
+ ulg  static_len;       
+ ulg  compressed_len;   
+ ulg  input_len;        
+ uns  last_flags;       
+ uch  flags;            
+ uns  last_lit;         
+ uns  last_dist;        
+ uch  flag_bit;         
+ int  heap_len;         
+ int  heap_max;         
+ ulg  bb;               
+ uns  bk;               
+ ush  bi_buf;           
+ int  bi_valid;         
+ uns  hufts;            
+ int  decrypt;          
+ int  ascii;            
+ int  msg_done;         
+ int  abortflag;        
+ int  decompress;       
+ int  do_lzw;           
+ int  to_stdout;        
+ int  force;            
+ int  verbose;
+ int  quiet;
+ int  list;             
+ int  test;             
+ int  ext_header;       
+ int  pkzip;            
+ int  method;           
+ int  level;            
+ int  no_time;          
+ int  no_name;          
+ int  exit_code;        
+ int  lbits;            
+ int  dbits;            
+ ulg  window_size;      
+ ulg  crc;              
+ ulg  adler;
+
+ uch  dist_code[512];
+ uch  length_code[MAX_MATCH-MIN_MATCH+1];
+ int  heap[2*L_CODES+1];
+ uch  depth[2*L_CODES+1];
+ int  base_length[LENGTH_CODES];
+ int  base_dist[D_CODES];
+ ush  bl_count[MAX_BITS+1];
+ uch  flag_buf[(LIT_BUFSIZE/8)];
+
+ #ifdef DYN_ALLOC
+ uch *inbuf;
+ uch *outbuf;
+ ush *d_buf;
+ uch *window;
+ #else
+ uch inbuf [INBUFSIZ +INBUF_EXTRA];
+ uch outbuf[OUTBUFSIZ+OUTBUF_EXTRA];
+ ush d_buf [DIST_BUFSIZE];
+ uch window[2L*WSIZE];
+ #endif
+
+ #ifdef FULL_SEARCH
+ #define nice_match MAX_MATCH
+ #else
+ int nice_match;
+ #endif
+
+ #ifdef CRYPT
+ uch cc;
+ #endif
+
+ ct_data static_ltree[L_CODES+2];
+ ct_data static_dtree[D_CODES];
+ ct_data dyn_dtree[(2*D_CODES+1)];
+ ct_data dyn_ltree[HEAP_SIZE];
+ ct_data bl_tree[2*BL_CODES+1];
+
+ tree_desc l_desc;
+ tree_desc d_desc;
+ tree_desc bl_desc;
+
+ #ifndef MAXSEG_64K
+
+ ush prev2[1L<<BITS];
+
+ #define prev gz1->prev2
+ #define head (gz1->prev2+WSIZE)
+
+ #else
+
+ ush * prev2;
+ ush * tab_prefix1;
+
+ #define prev gz1->prev2
+ #define head gz1->tab_prefix1
+
+ #endif
+
+} GZ1;
+typedef GZ1 *PGZ1;
+int gz1_size = sizeof( GZ1 );
+
+/* Declare some local function protypes... */
+
+/* Any routine name that can/might conflict with */
+/* other modules or object code should simply have */
+/* the standard prefix 'gz1_' added to the front. */
+/* This will only usually be any kind of problem at all */
+/* if the code is being compiled directly into the parent */
+/* instead of being built as a standalone DLL or DSO library. */
+
+PGZ1  gz1_init        ( void     );
+int   gz1_cleanup     ( PGZ1 gz1 );
+ulg   gz1_deflate     ( PGZ1 gz1 );
+ulg   gz1_deflate_fast( PGZ1 gz1 );
+
+/* The rest of the routines should not need the 'gz1_' prefix. */
+/* No conflicts reported at this time. */
+
+int   inflate        ( PGZ1 gz1 );
+int   inflate_dynamic( PGZ1 gz1 );
+int   inflate_stored ( PGZ1 gz1 );
+int   inflate_fixed  ( PGZ1 gz1 );
+void  fill_window    ( PGZ1 gz1 );
+void  flush_outbuf   ( PGZ1 gz1 );
+void  flush_window   ( PGZ1 gz1 );
+void  bi_windup      ( PGZ1 gz1 );
+void  set_file_type  ( PGZ1 gz1 );
+void  init_block     ( PGZ1 gz1 );
+int   build_bl_tree  ( PGZ1 gz1 );
+void  read_error     ( PGZ1 gz1 );
+void  write_error    ( PGZ1 gz1 );
+int   get_header     ( PGZ1 gz1, int in );
+int   inflate_block  ( PGZ1 gz1, int *e );
+int   fill_inbuf     ( PGZ1 gz1, int eof_ok );
+char *gz1_basename   ( PGZ1 gz1, char *fname );
+int   longest_match  ( PGZ1 gz1, unsigned cur_match );
+void  bi_init        ( PGZ1 gz1, gz1_file_t zipfile );
+int   file_read      ( PGZ1 gz1, char *buf, unsigned size );
+void  write_buf      ( PGZ1 gz1, int fd, voidp buf, unsigned cnt );
+
+void  error( char *msg   );
+
+/* XXX - Precomputed zlib header. If you change the window size or
+ * compression level from the defaults, this will break badly. The
+ * algorithm to build this is fairly complex; you can find it in
+ * the file deflate.c from the zlib distribution.
+ */
+#define ZLIB_HEADER "\170\9c"
+
+ulg adler32(ulg adler, uch *buf, unsigned len);
+
+int zip(
+PGZ1 gz1, 
+int  in,  
+int  out  
+);
+
+ulg flush_block(
+PGZ1  gz1,        
+char *buf,        
+ulg   stored_len, 
+int   eof         
+);
+
+void copy_block(
+PGZ1      gz1,    
+char     *buf,    
+unsigned  len,    
+int       header  
+);
+
+int ct_tally(
+PGZ1 gz1,  
+int  dist, 
+int  lc    
+);
+
+void send_bits(
+PGZ1 gz1,   
+int  value, 
+int  length 
+);
+
+void send_tree(
+PGZ1      gz1,     
+ct_data  *tree,    
+int       max_code 
+);
+
+void send_all_trees(
+PGZ1 gz1,    
+int  lcodes, 
+int  dcodes, 
+int  blcodes 
+);
+
+void ct_init(
+PGZ1  gz1,    
+ush  *attr,   
+int  *methodp 
+);
+
+void lm_init(
+PGZ1 gz1,        
+int  pack_level, 
+ush *flags       
+);
+
+void build_tree(
+PGZ1        gz1, 
+tree_desc  *desc 
+);
+
+void compress_block(
+PGZ1      gz1,   
+ct_data  *ltree, 
+ct_data  *dtree  
+);
+
+void gen_bitlen(
+PGZ1        gz1, 
+tree_desc  *desc 
+);
+
+void pqdownheap(
+PGZ1      gz1,  
+ct_data  *tree, 
+int       k     
+);
+
+int huft_build(
+PGZ1          gz1, 
+unsigned     *b,   
+unsigned      n,   
+unsigned      s,   
+ush          *d,   
+ush          *e,   
+struct huft **t,   
+int          *m    
+);
+
+ulg updcrc(
+PGZ1      gz1, 
+uch      *s,   
+unsigned  n    
+);
+
+int inflate_codes(
+PGZ1         gz1,  
+struct huft *tl,   
+struct huft *td,   
+int          bl,   
+int          bd    
+);
+
+void gen_codes(
+PGZ1      gz1,     
+ct_data  *tree,    
+int       max_code 
+);
+
+void scan_tree(
+PGZ1     gz1,     
+ct_data *tree,    
+int      max_code 
+);
+
+unsigned bi_reverse(
+PGZ1     gz1,  
+unsigned code, 
+int      len   
+);
+
+int huft_free(
+PGZ1         gz1, 
+struct huft *t    
+);
+
+PGZ1 gz1_init()
+{
+ PGZ1 gz1=0; 
+
+ gz1 = (PGZ1) malloc( gz1_size );
+
+ if ( !gz1 ) 
+   {
+    return 0; 
+   }
+
+ memset( gz1, 0, gz1_size );
+
+ ALLOC(uch, gz1->inbuf,  INBUFSIZ +INBUF_EXTRA);
+
+ if ( !gz1->inbuf ) 
+   {
+    free( gz1 ); 
+    return 0;    
+   }
+
+ ALLOC(uch, gz1->outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
+ if ( !gz1->outbuf ) 
+   {
+    FREE( gz1->inbuf  ); 
+    free( gz1         ); 
+    return 0;            
+   }
+
+ ALLOC(ush, gz1->d_buf,  DIST_BUFSIZE);
+
+ if ( !gz1->d_buf ) 
+   {
+    FREE( gz1->outbuf ); 
+    FREE( gz1->inbuf  ); 
+    free( gz1         ); 
+    return 0;            
+   }
+
+ ALLOC(uch, gz1->window, 2L*WSIZE);
+
+ if ( !gz1->window ) 
+   {
+    FREE( gz1->d_buf  ); 
+    FREE( gz1->outbuf ); 
+    FREE( gz1->inbuf  ); 
+    free( gz1         ); 
+    return 0;            
+   }
+
+ #ifndef MAXSEG_64K
+ #else 
+ ALLOC(ush, gz1->prev2, 1L<<(BITS-1) );
+
+ if ( !gz1->prev2 ) 
+   {
+    FREE( gz1->window ); 
+    FREE( gz1->d_buf  ); 
+    FREE( gz1->outbuf ); 
+    FREE( gz1->inbuf  ); 
+    free( gz1         ); 
+    return 0;            
+   }
+
+ ALLOC(ush, gz1->tab_prefix1, 1L<<(BITS-1) );
+
+ if ( !gz1->tab_prefix1 ) 
+   {
+    FREE( gz1->prev2  ); 
+    FREE( gz1->window ); 
+    FREE( gz1->d_buf  ); 
+    FREE( gz1->outbuf ); 
+    FREE( gz1->inbuf  ); 
+    free( gz1         ); 
+    return 0;            
+   }
+
+ #endif 
+
+ gz1->method      = DEFLATED;     
+ gz1->level       = 6;            
+ gz1->no_time     = -1;           
+ gz1->no_name     = -1;           
+ gz1->exit_code   = OK;           
+ gz1->lbits       = 9;            
+ gz1->dbits       = 6;            
+
+ gz1->window_size = (ulg)2*WSIZE;     
+ gz1->crc         = (ulg)0xffffffffL; 
+
+ gz1->d_desc.dyn_tree     = (ct_data *) gz1->dyn_dtree;
+ gz1->d_desc.static_tree  = (ct_data *) gz1->static_dtree;
+ gz1->d_desc.extra_bits   = (int     *) extra_dbits; 
+ gz1->d_desc.extra_base   = (int      ) 0;
+ gz1->d_desc.elems        = (int      ) D_CODES;
+ gz1->d_desc.max_length   = (int      ) MAX_BITS;
+ gz1->d_desc.max_code     = (int      ) 0;
+
+ gz1->l_desc.dyn_tree     = (ct_data *) gz1->dyn_ltree;
+ gz1->l_desc.static_tree  = (ct_data *) gz1->static_ltree;
+ gz1->l_desc.extra_bits   = (int     *) extra_lbits; 
+ gz1->l_desc.extra_base   = (int      ) LITERALS+1;
+ gz1->l_desc.elems        = (int      ) L_CODES;
+ gz1->l_desc.max_length   = (int      ) MAX_BITS;
+ gz1->l_desc.max_code     = (int      ) 0;
+
+ gz1->bl_desc.dyn_tree    = (ct_data *) gz1->bl_tree;
+ gz1->bl_desc.static_tree = (ct_data *) 0;
+ gz1->bl_desc.extra_bits  = (int     *) extra_blbits; 
+ gz1->bl_desc.extra_base  = (int      ) 0;
+ gz1->bl_desc.elems       = (int      ) BL_CODES;
+ gz1->bl_desc.max_length  = (int      ) MAX_BL_BITS;
+ gz1->bl_desc.max_code    = (int      ) 0;
+
+ return (PGZ1) gz1;
+
+}
+
+int gz1_cleanup( PGZ1 gz1 )
+{
+ #ifndef MAXSEG_64K
+ #else
+ FREE( gz1->tab_prefix1 );
+ FREE( gz1->prev2       );
+ #endif 
+
+ FREE( gz1->window ); 
+ FREE( gz1->d_buf  ); 
+ FREE( gz1->outbuf ); 
+ FREE( gz1->inbuf  ); 
+
+ free( gz1 ); 
+ gz1 = 0;     
+
+ return 0;
+}
+
+int (*read_buf)(PGZ1 gz1, char *buf, unsigned size);
+
+void error( char *msg )
+{
+ msg = msg;
+}
+
+int (*work)( PGZ1 gz1, int infile, int outfile ) = 0; 
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+
+int get_header( PGZ1 gz1, int in )
+{
+ uch       flags;    
+ char      magic[2]; 
+ ulg       stamp;    
+ unsigned  len;      
+ unsigned  part;     
+
+ if ( gz1->force && gz1->to_stdout )
+   {
+    magic[0] = (char)try_byte();
+    magic[1] = (char)try_byte();
+   }
+ else
+   {
+    magic[0] = (char)get_byte();
+    magic[1] = (char)get_byte();
+   }
+
+ gz1->method       = -1;        
+ gz1->header_bytes = 0;         
+ gz1->last_member  = RECORD_IO; 
+ gz1->part_nb++;                
+
+ if ( memcmp(magic, GZIP_MAGIC,     2 ) == 0 ||
+      memcmp(magic, OLD_GZIP_MAGIC, 2 ) == 0 )
+   {
+    gz1->method = (int)get_byte();
+
+    if ( gz1->method != DEFLATED )
+      {
+       gz1->exit_code = LZ1_ERROR;
+
+       return -1;
+      }
+
+    return -1;
+
+    if ((flags & ENCRYPTED) != 0)
+      {
+       gz1->exit_code = LZ1_ERROR;
+       return -1;
+      }
+
+    if ((flags & CONTINUATION) != 0)
+      {
+       gz1->exit_code = LZ1_ERROR;
+       if ( gz1->force <= 1) return -1;
+      }
+
+    if ((flags & RESERVED) != 0)
+      {
+       gz1->exit_code = LZ1_ERROR;
+       if ( gz1->force <= 1)
+          return -1;
+      }
+
+    stamp  = (ulg)get_byte();
+       stamp |= ((ulg)get_byte()) << 8;
+       stamp |= ((ulg)get_byte()) << 16;
+       stamp |= ((ulg)get_byte()) << 24;
+
+    if ( stamp != 0 && !gz1->no_time )
+      {
+       gz1->time_stamp = stamp;
+      }
+
+    (void)get_byte(); 
+    (void)get_byte(); 
+
+    if ((flags & CONTINUATION) != 0)
+      {
+       part  = (unsigned)  get_byte();
+       part |= ((unsigned) get_byte())<<8;
+      }
+
+    if ((flags & EXTRA_FIELD) != 0)
+      {
+        len  = (unsigned)  get_byte();
+        len |= ((unsigned) get_byte())<<8;
+
+        while (len--) (void)get_byte();
+      }
+
+    if ((flags & COMMENT) != 0)
+      {
+       while (get_char() != 0)  ;
+      }
+
+    if ( gz1->part_nb == 1 )
+      {
+       gz1->header_bytes = gz1->inptr + 2*sizeof(long);
+      }
+   }
+
+ return gz1->method;
+}
+
+int fill_inbuf( PGZ1 gz1, int eof_ok )
+{
+ int len;
+ int bytes_to_copy;
+
+ gz1->insize = 0;
+ errno       = 0;
+
+ do {
+     if ( gz1->input_ismem )
+       {
+        if ( gz1->input_bytesleft > 0 )
+          {
+           bytes_to_copy = INBUFSIZ - gz1->insize;
+
+           if ( bytes_to_copy > gz1->input_bytesleft )
+             {
+              bytes_to_copy = gz1->input_bytesleft;
+             }
+
+           memcpy(
+           (char*)gz1->inbuf+gz1->insize,
+           gz1->input_ptr,
+           bytes_to_copy
+           );
+
+           gz1->input_ptr       += bytes_to_copy;
+           gz1->input_bytesleft -= bytes_to_copy;
+
+           len = bytes_to_copy;
+          }
+        else 
+          {
+           len = 0; 
+          }
+       }
+     else 
+       {
+        len =
+        read(
+        gz1->ifd,
+        (char*)gz1->inbuf+gz1->insize,
+        INBUFSIZ-gz1->insize
+        );
+       }
+
+     if (len == 0 || len == EOF) break;
+
+     gz1->insize += len;
+
+    } while( gz1->insize < INBUFSIZ );
+
+ if ( gz1->insize == 0 )
+   {
+    if( eof_ok ) return EOF;
+    read_error( gz1 );
+   }
+
+ gz1->bytes_in += (ulg) gz1->insize;
+ gz1->inptr     = 1;
+
+ return gz1->inbuf[0];
+}
+
+ulg updcrc(
+PGZ1      gz1, 
+uch      *s,   
+unsigned  n    
+)
+{
+ register ulg c; 
+
+ if ( s == NULL )
+   {
+    c = 0xffffffffL;
+   }
+ else
+   {
+    c = gz1->crc;
+
+    if ( n )
+      {
+       do{
+          c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
+
+         } while( --n );
+      }
+   }
+
+ gz1->crc = c;
+
+ return( c ^ 0xffffffffL ); 
+}
+
+void read_error( PGZ1 gz1 )
+{
+ gz1->abortflag = 1;
+}
+
+void mod_gzip_strlwr( char *s )
+{
+ char *p1=s;
+
+ if ( s == 0 ) return;
+
+ while ( *p1 != 0 )
+   {
+    if ( *p1 > 96 ) *p1 = *p1 - 32;
+    p1++;
+   }
+}
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+
+char *gz1_basename( PGZ1 gz1, char *fname )
+{
+ char *p;
+
+ if ((p = strrchr(fname, PATH_SEP))  != NULL) fname = p+1;
+
+ #ifdef PATH_SEP2
+ if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
+ #endif
+
+ #ifdef PATH_SEP3
+ if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
+ #endif
+
+ #ifdef SUFFIX_SEP
+ if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
+ #endif
+
+ if (casemap('A') == 'a') mod_gzip_strlwr(fname);
+
+ return fname;
+}
+
+void write_buf( PGZ1 gz1, int fd, voidp buf, unsigned cnt )
+{
+ unsigned n;
+
+ if ( gz1->output_ismem )
+   {
+    if ( ( gz1->bytes_out + cnt ) < gz1->output_maxlen )
+      {
+       memcpy( gz1->output_ptr, buf, cnt );
+       gz1->output_ptr += cnt;
+      }
+    else
+      {
+       write_error( gz1 );
+      }
+   }
+ else
+   {
+    while ((n = write(fd, buf, cnt)) != cnt)
+      {
+       if (n == (unsigned)(-1))
+         {
+          write_error( gz1 );
+         }
+       cnt -= n;
+       buf = (voidp)((char*)buf+n);
+      }
+   }
+}
+
+void write_error( PGZ1 gz1 )
+{
+ gz1->abortflag = 1;
+}
+
+#ifdef __TURBOC__
+#ifndef BC55
+
+static ush ptr_offset = 0;
+
+void * fcalloc(
+unsigned items, 
+unsigned size   
+)
+{
+ void * buf = farmalloc((ulg)items*size + 16L);
+
+ if (buf == NULL) return NULL;
+
+ if (ptr_offset == 0)
+   {
+    ptr_offset = (ush)((uch*)buf-0);
+   }
+ else if (ptr_offset != (ush)((uch*)buf-0))
+   {
+    error("inconsistent ptr_offset");
+   }
+
+ *((ush*)&buf+1) += (ptr_offset + 15) >> 4;
+ *(ush*)&buf = 0;
+
+ return buf;
+}
+
+void fcfree( void *ptr )
+{
+ *((ush*)&ptr+1) -= (ptr_offset + 15) >> 4;
+ *(ush*)&ptr = ptr_offset;
+
+ farfree(ptr);
+}
+
+#endif 
+#endif 
+
+int zip(
+PGZ1 gz1, 
+int in,   
+int out   
+)
+{
+ uch  flags = 0;         
+ ush  attr  = 0;         
+ ush  deflate_flags = 0; 
+
+ gz1->ifd    = in;
+ gz1->ofd    = out;
+ gz1->outcnt = 0;
+
+ gz1->method = DEFLATED;
+
+ put_byte(GZIP_MAGIC[0]); 
+ put_byte(GZIP_MAGIC[1]);
+ put_byte(DEFLATED);      
+
+ if ( gz1->save_orig_name )
+   {
+       flags |= ORIG_NAME;
+   }
+
+ put_byte(flags);           
+ put_long(gz1->time_stamp); 
+
+ gz1->crc = -1; 
+
+ updcrc( gz1, NULL, 0 ); 
+
+ bi_init( gz1, out );
+ ct_init( gz1, &attr, &gz1->method );
+ lm_init( gz1, gz1->level, &deflate_flags );
+
+ put_byte((uch)deflate_flags); 
+
+ put_byte(OS_CODE); 
+
+ if ( gz1->save_orig_name )
+   {
+    char *p = gz1_basename( gz1, gz1->ifname );
+
+    do {
+           put_char(*p);
+
+       } while (*p++);
+   }
+
+ gz1->header_bytes = (long)gz1->outcnt;
+
+ (void) gz1_deflate( gz1 );
+
+ put_long( gz1->crc      );
+ put_long( gz1->bytes_in );
+
+ gz1->header_bytes += 2*sizeof(long);
+
+ flush_outbuf( gz1 );
+
+ return OK;
+}
+
+ulg gz1_deflate( PGZ1 gz1 )
+{
+    unsigned hash_head;      
+    unsigned prev_match;     
+    int flush;               
+    int match_available = 0; 
+    register unsigned match_length = MIN_MATCH-1; 
+#ifdef DEBUG
+    long isize;        
+#endif
+
+    if (gz1->compr_level <= 3)
+      {
+       return gz1_deflate_fast(gz1);
+      }
+
+    while (gz1->lookahead != 0)
+      {
+       gz1->ins_h =
+       (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[gz1->strstart+MIN_MATCH-1])) & HASH_MASK;
+
+       prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ];
+
+       head[ gz1->ins_h ] = gz1->strstart;
+
+        gz1->prev_length = match_length, prev_match = gz1->match_start;
+        match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && gz1->prev_length < gz1->max_lazy_match &&
+            gz1->strstart - hash_head <= MAX_DIST) {
+            
+            match_length = longest_match( gz1, hash_head );
+            
+            if (match_length > gz1->lookahead) match_length = gz1->lookahead;
+
+            if (match_length == MIN_MATCH && gz1->strstart-gz1->match_start > TOO_FAR){
+                
+                match_length--;
+            }
+        }
+        
+        if (gz1->prev_length >= MIN_MATCH && match_length <= gz1->prev_length) {
+
+            flush = ct_tally(gz1,gz1->strstart-1-prev_match, gz1->prev_length - MIN_MATCH);
+
+            gz1->lookahead        -= ( gz1->prev_length - 1 );
+            gz1->prev_length -= 2;
+
+            do {
+                gz1->strstart++;
+
+                gz1->ins_h =
+                (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK;
+
+                prev[ gz1->strstart & WMASK ] = hash_head = head[gz1->ins_h];
+
+                head[ gz1->ins_h ] = gz1->strstart;
+
+            } while (--gz1->prev_length != 0);
+            match_available = 0;
+            match_length = MIN_MATCH-1;
+            gz1->strstart++;
+            if (flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
+
+        } else if (match_available) {
+            
+            if (ct_tally( gz1, 0, gz1->window[gz1->strstart-1] )) {
+                FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
+            }
+            gz1->strstart++;
+            gz1->lookahead--;
+        } else {
+            
+            match_available = 1;
+            gz1->strstart++;
+            gz1->lookahead--;
+        }
+        
+        while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) fill_window(gz1);
+    }
+    if (match_available) ct_tally( gz1, 0, gz1->window[gz1->strstart-1] );
+
+    return FLUSH_BLOCK(1); 
+
+ return 0;
+}
+
+void flush_outbuf( PGZ1 gz1 )
+{
+ if ( gz1->outcnt == 0 )
+   {
+    return;
+   }
+
+ write_buf( gz1, gz1->ofd, (char *)gz1->outbuf, gz1->outcnt );
+
+ gz1->bytes_out += (ulg)gz1->outcnt;
+ gz1->outcnt = 0;
+}
+
+void lm_init(
+PGZ1 gz1,        
+int  pack_level, 
+ush *flags       
+)
+{
+ register unsigned j;
+
+ if ( pack_level < 1 || pack_level > 9 )
+   {
+    error("bad pack level");
+   }
+
+ gz1->compr_level = pack_level;
+
+ #if defined(MAXSEG_64K) && HASH_BITS == 15
+ for (j = 0;  j < HASH_SIZE; j++) head[j] = NIL;
+ #else
+ memset( (char*)head, 0, (HASH_SIZE*sizeof(*head)) );
+ #endif
+
+ gz1->max_lazy_match   = configuration_table[pack_level].max_lazy;
+ gz1->good_match       = configuration_table[pack_level].good_length;
+ #ifndef FULL_SEARCH
+ gz1->nice_match       = configuration_table[pack_level].nice_length;
+ #endif
+ gz1->max_chain_length = configuration_table[pack_level].max_chain;
+
+ if ( pack_level == 1 )
+   {
+    *flags |= FAST;
+   }
+ else if ( pack_level == 9 )
+   {
+    *flags |= SLOW;
+   }
+
+ gz1->strstart    = 0;
+ gz1->block_start = 0L;
+ #ifdef ASMV
+ match_init(); 
+ #endif
+
+ gz1->lookahead = read_buf(gz1,(char*)gz1->window,
+                  sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE);
+
+ if (gz1->lookahead == 0 || gz1->lookahead == (unsigned)EOF)
+   {
+    gz1->eofile = 1, gz1->lookahead = 0;
+    return;
+   }
+
+ gz1->eofile = 0;
+
+ while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile)
+   {
+    fill_window(gz1);
+   }
+
+ gz1->ins_h = 0;
+
+ for ( j=0; j<MIN_MATCH-1; j++ )
+    {
+     gz1->ins_h =
+     (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[j])) & HASH_MASK;
+    }
+}
+
+void fill_window( PGZ1 gz1 )
+{
+ register unsigned n, m;
+
+ unsigned more =
+ (unsigned)( gz1->window_size - (ulg)gz1->lookahead - (ulg)gz1->strstart );
+
+ if ( more == (unsigned)EOF)
+   {
+    more--;
+   }
+ else if ( gz1->strstart >= WSIZE+MAX_DIST )
+   {
+    memcpy((char*)gz1->window, (char*)gz1->window+WSIZE, (unsigned)WSIZE);
+
+    gz1->match_start -= WSIZE;
+    gz1->strstart    -= WSIZE; 
+
+    gz1->block_start -= (long) WSIZE;
+
+    for ( n = 0; n < HASH_SIZE; n++ )
+       {
+        m = head[n];
+        head[n] = (ush)(m >= WSIZE ? m-WSIZE : NIL);
+       }
+
+    for ( n = 0; n < WSIZE; n++ )
+       {
+        m = prev[n];
+
+        prev[n] = (ush)(m >= WSIZE ? m-WSIZE : NIL);
+       }
+
+    more += WSIZE;
+   }
+
+ if ( !gz1->eofile )
+   {
+    n = read_buf(gz1,(char*)gz1->window+gz1->strstart+gz1->lookahead, more);
+
+    if ( n == 0 || n == (unsigned)EOF )
+      {
+       gz1->eofile = 1;
+      }
+    else
+      {
+       gz1->lookahead += n;
+      }
+   }
+}
+
+ulg gz1_deflate_fast( PGZ1 gz1 )
+{
+    unsigned hash_head; 
+    int flush;      
+    unsigned match_length = 0;  
+
+    gz1->prev_length = MIN_MATCH-1;
+
+    while (gz1->lookahead != 0)
+      {
+       gz1->ins_h =
+       (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK;
+       
+       prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ];
+
+       head[ gz1->ins_h ] = gz1->strstart;
+
+        if (hash_head != NIL && gz1->strstart - hash_head <= MAX_DIST) {
+            
+            match_length = longest_match( gz1, hash_head );
+            
+            if (match_length > gz1->lookahead) match_length = gz1->lookahead;
+        }
+        if (match_length >= MIN_MATCH) {
+
+            flush = ct_tally(gz1,gz1->strstart-gz1->match_start, match_length - MIN_MATCH);
+
+            gz1->lookahead -= match_length;
+
+            if (match_length <= gz1->max_lazy_match )
+              {
+                match_length--; 
+
+                do {
+                    gz1->strstart++;
+
+                    gz1->ins_h =
+                    (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK;
+                    
+                    prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ];
+
+                    head[ gz1->ins_h ] = gz1->strstart;
+
+                } while (--match_length != 0);
+            gz1->strstart++;
+            } else {
+            gz1->strstart += match_length;
+               match_length = 0;
+            gz1->ins_h = gz1->window[gz1->strstart];
+
+            gz1->ins_h =
+            (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[gz1->strstart+1])) & HASH_MASK;
+            
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+            }
+        } else {
+            
+            flush = ct_tally(gz1, 0, gz1->window[gz1->strstart]);
+            gz1->lookahead--;
+        gz1->strstart++;
+        }
+        if (flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
+
+        while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) fill_window(gz1);
+    }
+
+ return FLUSH_BLOCK(1);
+}
+
+void ct_init(
+PGZ1  gz1,    
+ush  *attr,   
+int  *methodp 
+)
+{
+ #ifdef DD1
+ int i,ii;
+ #endif
+
+ int n;      
+ int bits;   
+ int length; 
+ int code;   
+ int dist;   
+
+ gz1->file_type      = attr;
+ gz1->file_method    = methodp;
+ gz1->compressed_len = gz1->input_len = 0L;
+        
+ if ( gz1->static_dtree[0].dl.len != 0 )
+   {
+    return;
+   }
+
+ length = 0;
+
+ for ( code = 0; code < LENGTH_CODES-1; code++ )
+    {
+     gz1->base_length[code] = length;
+
+     for ( n = 0; n < (1<<extra_lbits[code]); n++ )
+        {
+         gz1->length_code[length++] = (uch)code;
+        }
+    }
+
+ gz1->length_code[length-1] = (uch)code;
+
+ dist = 0;
+
+ for ( code = 0 ; code < 16; code++ )
+    {
+     gz1->base_dist[code] = dist;
+
+     for ( n = 0; n < (1<<extra_dbits[code]); n++ )
+        {
+         gz1->dist_code[dist++] = (uch)code;
+        }
+    }
+
+ dist >>= 7; 
+
+ for ( ; code < D_CODES; code++ )
+    {
+     gz1->base_dist[code] = dist << 7;
+
+     for ( n = 0; n < (1<<(extra_dbits[code]-7)); n++ )
+        {
+         gz1->dist_code[256 + dist++] = (uch)code;
+        }
+    }
+
+ for ( bits = 0; bits <= MAX_BITS; bits++ )
+    {
+     gz1->bl_count[bits] = 0;
+    }
+
+ n = 0;
+
+ while (n <= 143) gz1->static_ltree[n++].dl.len = 8, gz1->bl_count[8]++;
+ while (n <= 255) gz1->static_ltree[n++].dl.len = 9, gz1->bl_count[9]++;
+ while (n <= 279) gz1->static_ltree[n++].dl.len = 7, gz1->bl_count[7]++;
+ while (n <= 287) gz1->static_ltree[n++].dl.len = 8, gz1->bl_count[8]++;
+
+ gen_codes(gz1,(ct_data *)gz1->static_ltree, L_CODES+1);
+
+ for ( n = 0; n < D_CODES; n++ )
+    {
+     gz1->static_dtree[n].dl.len  = 5;
+     gz1->static_dtree[n].fc.code = bi_reverse( gz1, n, 5 );
+    }
+
+ init_block( gz1 );
+}
+
+ulg flush_block(
+PGZ1  gz1,        
+char *buf,        
+ulg   stored_len, 
+int   eof         
+)
+{
+ ulg opt_lenb;     
+ ulg static_lenb;  
+ int max_blindex;  
+
+ gz1->flag_buf[gz1->last_flags] = gz1->flags;
+
+ if (*gz1->file_type == (ush)UNKNOWN) set_file_type(gz1);
+
+ build_tree( gz1, (tree_desc *)(&gz1->l_desc) );
+ build_tree( gz1, (tree_desc *)(&gz1->d_desc) );
+
+ max_blindex = build_bl_tree( gz1 );
+
+ opt_lenb         = (gz1->opt_len+3+7)>>3;
+ static_lenb      = (gz1->static_len+3+7)>>3;
+ gz1->input_len  += stored_len; 
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+#ifdef FORCE_METHOD
+ if ( level == 1 && eof && gz1->compressed_len == 0L )
+#else
+ if (stored_len <= opt_lenb && eof && gz1->compressed_len == 0L && 0 )
+#endif
+   {
+    if (buf == (char*)0) error ("block vanished");
+
+    copy_block( gz1, buf, (unsigned)stored_len, 0 ); 
+
+    gz1->compressed_len = stored_len << 3;
+    *gz1->file_method   = STORED;
+
+#ifdef FORCE_METHOD
+ } else if (level == 2 && buf != (char*)0) { 
+#else
+ } else if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+                    
+#endif
+     
+     send_bits(gz1,(STORED_BLOCK<<1)+eof, 3);  
+     gz1->compressed_len = (gz1->compressed_len + 3 + 7) & ~7L;
+     gz1->compressed_len += (stored_len + 4) << 3;
+
+     copy_block(gz1, buf, (unsigned)stored_len, 1); 
+
+#ifdef FORCE_METHOD
+ } else if (level == 3) { 
+#else
+ } else if (static_lenb == opt_lenb) {
+#endif
+     send_bits(gz1,(STATIC_TREES<<1)+eof, 3);
+
+     compress_block(
+     gz1,
+     (ct_data *)gz1->static_ltree,
+     (ct_data *)gz1->static_dtree
+     );
+
+     gz1->compressed_len += 3 + gz1->static_len;
+    }
+  else
+    {
+     send_bits(gz1,(DYN_TREES<<1)+eof, 3);
+
+     send_all_trees(
+     gz1,
+     gz1->l_desc.max_code+1,
+     gz1->d_desc.max_code+1,
+     max_blindex+1
+     );
+
+     compress_block(
+     gz1,
+     (ct_data *)gz1->dyn_ltree,
+     (ct_data *)gz1->dyn_dtree
+     );
+
+     gz1->compressed_len += 3 + gz1->opt_len;
+    }
+
+ init_block( gz1 );
+
+ if ( eof )
+   {
+    bi_windup( gz1 );
+
+    gz1->compressed_len += 7;  
+   }
+
+ return gz1->compressed_len >> 3;
+}
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+
+unsigned bi_reverse(
+PGZ1     gz1,  
+unsigned code, 
+int      len   
+)
+{
+ register unsigned res = 0;
+
+ do {
+     res |= code & 1;
+     code >>= 1, res <<= 1;
+
+    } while (--len > 0);
+
+ return res >> 1;
+}
+
+void set_file_type( PGZ1 gz1 )
+{
+ int n = 0;
+ unsigned ascii_freq = 0;
+ unsigned bin_freq = 0;
+
+ while (n < 7)        bin_freq += gz1->dyn_ltree[n++].fc.freq;
+ while (n < 128)    ascii_freq += gz1->dyn_ltree[n++].fc.freq;
+ while (n < LITERALS) bin_freq += gz1->dyn_ltree[n++].fc.freq;
+
+ *gz1->file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
+}
+
+void init_block( PGZ1 gz1 )
+{
+ int n; 
+
+ for (n = 0; n < L_CODES;  n++) gz1->dyn_ltree[n].fc.freq = 0;
+ for (n = 0; n < D_CODES;  n++) gz1->dyn_dtree[n].fc.freq = 0;
+ for (n = 0; n < BL_CODES; n++) gz1->bl_tree[n].fc.freq   = 0;
+
+ gz1->dyn_ltree[END_BLOCK].fc.freq = 1;
+
+ gz1->opt_len    = 0L;
+ gz1->static_len = 0L;
+ gz1->last_lit   = 0;
+ gz1->last_dist  = 0;
+ gz1->last_flags = 0;
+ gz1->flags      = 0;
+ gz1->flag_bit   = 1;
+}
+
+void bi_init( PGZ1 gz1, gz1_file_t zipfile )
+{
+ gz1->zfile    = zipfile;
+ gz1->bi_buf   = 0;
+ gz1->bi_valid = 0;
+
+ if ( gz1->zfile != NO_FILE )
+   {
+    read_buf = file_read;
+   }
+}
+
+int ct_tally(
+PGZ1 gz1,  
+int  dist, 
+int  lc    
+)
+{
+ int dcode;
+
+ gz1->inbuf[gz1->last_lit++] = (uch)lc;
+
+ if ( dist == 0 )
+   {
+    gz1->dyn_ltree[lc].fc.freq++; 
+   }
+ else
+   {
+    dist--; 
+
+    gz1->dyn_ltree[gz1->length_code[lc]+LITERALS+1].fc.freq++;
+    gz1->dyn_dtree[d_code(dist)].fc.freq++;
+    gz1->d_buf[gz1->last_dist++] = (ush)dist;
+    gz1->flags |= gz1->flag_bit;
+   }
+
+ gz1->flag_bit <<= 1;
+
+ if ( (gz1->last_lit & 7) == 0 )
+   {
+    gz1->flag_buf[gz1->last_flags++] = gz1->flags;
+    gz1->flags = 0, gz1->flag_bit = 1;
+   }
+
+ if ( gz1->level > 2 && (gz1->last_lit & 0xfff) == 0)
+   {
+    ulg out_length = (ulg) ( gz1->last_lit * 8L );
+    ulg in_length  = (ulg) ( gz1->strstart - gz1->block_start );
+
+    for ( dcode = 0; dcode < D_CODES; dcode++ )
+       {
+        out_length += (ulg) ((gz1->dyn_dtree[dcode].fc.freq)*(5L+extra_dbits[dcode]));
+       }
+
+    out_length >>= 3;
+
+    if ( gz1->last_dist < gz1->last_lit/2 && out_length < in_length/2 )
+      {
+       return 1;
+      }
+   }
+
+ return( gz1->last_lit == LIT_BUFSIZE-1 || gz1->last_dist == DIST_BUFSIZE );
+}
+
+void compress_block(
+PGZ1     gz1,   
+ct_data *ltree, 
+ct_data *dtree  
+)
+{
+ unsigned dist;   
+ int lc;          
+ unsigned lx = 0; 
+ unsigned dx = 0; 
+ unsigned fx = 0; 
+ uch flag = 0;    
+ unsigned code;   
+ int extra;       
+
+ if (gz1->last_lit != 0) do {
+     if ((lx & 7) == 0) flag = gz1->flag_buf[fx++];
+     lc = gz1->inbuf[lx++];
+     if ((flag & 1) == 0) {
+         send_code(lc, ltree); 
+     } else {
+         
+         code = gz1->length_code[lc];
+         send_code(code+LITERALS+1, ltree); 
+         extra = extra_lbits[code];
+         if (extra != 0) {
+             lc -= gz1->base_length[code];
+             send_bits(gz1,lc, extra); 
+         }
+         dist = gz1->d_buf[dx++];
+         
+         code = d_code(dist);
+
+         send_code(code, dtree);       
+         extra = extra_dbits[code];
+         if (extra != 0) {
+             dist -= gz1->base_dist[code];
+             send_bits(gz1,dist, extra); 
+         }
+     } 
+     flag >>= 1;
+ } while (lx < gz1->last_lit);
+
+ send_code(END_BLOCK, ltree);
+}
+
+#ifndef ASMV
+
+int longest_match( PGZ1 gz1, unsigned cur_match )
+{
+ unsigned chain_length = gz1->max_chain_length;   
+ register uch *scan = gz1->window + gz1->strstart;     
+ register uch *match;                        
+ register int len;                           
+ int best_len = gz1->prev_length;                 
+ unsigned limit = gz1->strstart > (unsigned)MAX_DIST ? gz1->strstart - (unsigned)MAX_DIST : NIL;
+#if HASH_BITS < 8 || MAX_MATCH != 258
+   error: Code too clever
+#endif
+
+#ifdef UNALIGNED_OK
+    
+    register uch *strend    = gz1->window + gz1->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ush*)scan;
+    register ush scan_end   = *(ush*)(scan+best_len-1);
+#else
+    register uch *strend    = gz1->window + gz1->strstart + MAX_MATCH;
+    register uch scan_end1  = scan[best_len-1];
+    register uch scan_end   = scan[best_len];
+#endif
+
+    if (gz1->prev_length >= gz1->good_match) {
+        chain_length >>= 2;
+    }
+
+    do {
+        match = gz1->window + cur_match;
+
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        
+        if (*(ush*)(match+best_len-1) != scan_end ||
+            *(ush*)match != scan_start) continue;
+
+        scan++, match++;
+        do {
+        } while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
+                 *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+                 *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+                 *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+                 scan < strend);
+        
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+#else 
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        scan += 2, match++;
+
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+#endif 
+        if (len > best_len) {
+            gz1->match_start = cur_match;
+            best_len = len;
+            if (len >= gz1->nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ush*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & WMASK]) > limit
+            && --chain_length != 0);
+
+    return best_len;
+}
+#endif 
+
+void send_bits(
+PGZ1 gz1,   
+int  value, 
+int  length 
+)
+{
+ if ( gz1->bi_valid > (int) BUFSIZE - length )
+   {
+    gz1->bi_buf |= (value << gz1->bi_valid);
+
+    put_short(gz1->bi_buf);
+
+    gz1->bi_buf = (ush)value >> (BUFSIZE - gz1->bi_valid);
+    gz1->bi_valid += length - BUFSIZE;
+   }
+ else
+   {
+    gz1->bi_buf |= value << gz1->bi_valid;
+    gz1->bi_valid += length;
+   }
+}
+
+void build_tree(
+PGZ1       gz1, 
+tree_desc *desc 
+)
+{
+ int elems      = desc->elems;
+ ct_data *tree  = desc->dyn_tree;
+ ct_data *stree = desc->static_tree;
+
+ int n;             
+ int m;             
+ int max_code = -1; 
+ int node = elems;  
+ int new1;          
+
+    gz1->heap_len = 0, gz1->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].fc.freq != 0) {
+            gz1->heap[++gz1->heap_len] = max_code = n;
+            gz1->depth[n] = 0;
+        } else {
+            tree[n].dl.len = 0;
+        }
+    }
+
+    while (gz1->heap_len < 2) {
+        new1 = gz1->heap[++gz1->heap_len] = (max_code < 2 ? ++max_code : 0);
+        tree[new1].fc.freq = 1;
+        gz1->depth[new1] = 0;
+        gz1->opt_len--; if (stree) gz1->static_len -= stree[new1].dl.len;
+    }
+    desc->max_code = max_code;
+
+    for (n = gz1->heap_len/2; n >= 1; n--) pqdownheap(gz1, tree, n);
+
+    do {
+        n = gz1->heap[SMALLEST];
+        gz1->heap[SMALLEST] = gz1->heap[gz1->heap_len--];
+        pqdownheap(gz1, tree, SMALLEST);
+        m = gz1->heap[SMALLEST];
+        gz1->heap[--gz1->heap_max] = n;
+        gz1->heap[--gz1->heap_max] = m;
+        tree[node].fc.freq = tree[n].fc.freq + tree[m].fc.freq;
+        gz1->depth[node] = (uch) (GZ1_MAX(gz1->depth[n], gz1->depth[m]) + 1);
+        tree[n].dl.dad = tree[m].dl.dad = (ush)node;
+        gz1->heap[SMALLEST] = node++;
+        pqdownheap(gz1, tree, SMALLEST);
+
+    } while (gz1->heap_len >= 2);
+
+    gz1->heap[--gz1->heap_max] = gz1->heap[SMALLEST];
+
+    gen_bitlen(gz1,(tree_desc *)desc);
+
+    gen_codes(gz1,(ct_data *)tree, max_code);
+}
+
+int build_bl_tree( PGZ1 gz1 )
+{
+ int max_blindex; 
+
+ scan_tree( gz1, (ct_data *)gz1->dyn_ltree, gz1->l_desc.max_code );
+ scan_tree( gz1, (ct_data *)gz1->dyn_dtree, gz1->d_desc.max_code );
+
+ build_tree( gz1, (tree_desc *)(&gz1->bl_desc) );
+
+ for ( max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex-- )
+    {
+     if (gz1->bl_tree[bl_order[max_blindex]].dl.len != 0) break;
+    }
+
+ gz1->opt_len += 3*(max_blindex+1) + 5+5+4;
+
+ return max_blindex;
+}
+
+void gen_codes(
+PGZ1     gz1,     
+ct_data *tree,    
+int      max_code 
+)
+{
+ ush next_code[MAX_BITS+1]; 
+ ush code = 0;              
+ int bits;                  
+ int n;                     
+
+ for ( bits = 1; bits <= MAX_BITS; bits++ )
+    {
+     next_code[bits] = code = (code + gz1->bl_count[bits-1]) << 1;
+    }
+
+ for ( n = 0;  n <= max_code; n++ )
+    {
+     int len = tree[n].dl.len;
+     if (len == 0) continue;
+
+     tree[n].fc.code = bi_reverse( gz1, next_code[len]++, len );
+    }
+
+ return;
+}
+
+void gen_bitlen(
+PGZ1       gz1, 
+tree_desc *desc 
+)
+{
+ ct_data *tree   = desc->dyn_tree;
+ int *extra      = desc->extra_bits;
+ int base             = desc->extra_base;
+ int max_code         = desc->max_code;
+ int max_length       = desc->max_length;
+ ct_data *stree  = desc->static_tree;
+ int h;              
+ int n, m;           
+ int bits;           
+ int xbits;          
+ ush f;              
+ int overflow = 0;   
+
+ for (bits = 0; bits <= MAX_BITS; bits++) gz1->bl_count[bits] = 0;
+
+ tree[gz1->heap[gz1->heap_max]].dl.len = 0;
+
+ for (h = gz1->heap_max+1; h < HEAP_SIZE; h++) {
+     n = gz1->heap[h];
+     bits = tree[tree[n].dl.dad].dl.len + 1;
+     if (bits > max_length) bits = max_length, overflow++;
+     tree[n].dl.len = (ush)bits;
+     
+     if (n > max_code) continue; 
+
+     gz1->bl_count[bits]++;
+     xbits = 0;
+     if (n >= base) xbits = extra[n-base];
+     f = tree[n].fc.freq;
+     gz1->opt_len += (ulg)f * (bits + xbits);
+     if (stree) gz1->static_len += (ulg)f * (stree[n].dl.len + xbits);
+ }
+ if (overflow == 0) return;
+
+ do {
+     bits = max_length-1;
+     while (gz1->bl_count[bits] == 0) bits--;
+     gz1->bl_count[bits]--;      
+     gz1->bl_count[bits+1] += 2; 
+     gz1->bl_count[max_length]--;
+     
+     overflow -= 2;
+ } while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--) {
+     n = gz1->bl_count[bits];
+     while (n != 0) {
+         m = gz1->heap[--h];
+         if (m > max_code) continue;
+         if (tree[m].dl.len != (unsigned) bits) {
+             gz1->opt_len += ((long)bits-(long)tree[m].dl.len)*(long)tree[m].fc.freq;
+             tree[m].dl.len = (ush)bits;
+         }
+         n--;
+     }
+  }
+}
+
+void copy_block(
+PGZ1      gz1,    
+char     *buf,    
+unsigned  len,    
+int       header  
+)
+{
+ #ifdef CRYPT
+ int t;
+ #endif
+
+ bi_windup( gz1 ); 
+
+ if ( header )
+   {
+    put_short((ush)len);
+    put_short((ush)~len);
+   }
+
+ while( len-- )
+   {
+    #ifdef CRYPT
+       if (key) zencode(*buf, t);
+    #endif
+
+    put_byte(*buf++);
+   }
+}
+
+int file_read( PGZ1 gz1, char *buf, unsigned size )
+{
+ unsigned len = 0;
+ unsigned bytes_to_copy = 0;
+
+ if ( gz1->input_ismem )
+   {
+    if ( gz1->input_bytesleft > 0 )
+      {
+       bytes_to_copy = size;
+
+       if ( bytes_to_copy > (unsigned) gz1->input_bytesleft )
+         {
+          bytes_to_copy = (unsigned) gz1->input_bytesleft;
+         }
+
+       memcpy( buf, gz1->input_ptr, bytes_to_copy );
+
+       gz1->input_ptr       += bytes_to_copy;
+       gz1->input_bytesleft -= bytes_to_copy;
+
+       len = bytes_to_copy;
+      }
+    else
+      {
+       len = 0;
+      }
+   }
+ else
+   {
+    len = read( gz1->ifd, buf, size );
+   }
+
+ if ( len == (unsigned)(-1) || len == 0 )
+   {
+       gz1->crc = gz1->crc ^ 0xffffffffL;
+    /* XXX - Do we need to do something with Adler CRC's here?
+        * I don't think so--they don't seem to need postprocessing. */
+    return (int)len;
+   }
+
+ if (gz1->compression_format != DEFLATE_FORMAT)
+   {
+    updcrc( gz1, (uch*)buf, len );
+   }
+ else
+   {
+       gz1->adler = adler32(gz1->adler, (uch*)buf, len);
+   }
+
+ gz1->bytes_in += (ulg)len;
+
+ return (int)len;
+}
+
+void bi_windup( PGZ1 gz1 )
+{
+ if ( gz1->bi_valid > 8 )
+   {
+    put_short(gz1->bi_buf);
+   }
+ else if ( gz1->bi_valid > 0 )
+   {
+    put_byte(gz1->bi_buf);
+   }
+
+ gz1->bi_buf   = 0;
+ gz1->bi_valid = 0;
+}
+
+void send_all_trees(
+PGZ1 gz1,    
+int  lcodes, 
+int  dcodes, 
+int  blcodes 
+)
+{
+ int rank; 
+
+ send_bits(gz1,lcodes-257, 5); 
+ send_bits(gz1,dcodes-1,   5);
+ send_bits(gz1,blcodes-4,  4); 
+
+ for ( rank = 0; rank < blcodes; rank++ )
+    {
+     send_bits(gz1,gz1->bl_tree[bl_order[rank]].dl.len, 3 );
+    }
+
+ send_tree(gz1,(ct_data *)gz1->dyn_ltree, lcodes-1); 
+ send_tree(gz1,(ct_data *)gz1->dyn_dtree, dcodes-1); 
+}
+
+void send_tree(
+PGZ1     gz1,     
+ct_data *tree,    
+int      max_code 
+)
+{
+ int n;                        
+ int prevlen = -1;             
+ int curlen;                   
+ int nextlen = tree[0].dl.len; 
+ int count = 0;                
+ int max_count = 7;            
+ int min_count = 4;            
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for ( n = 0; n <= max_code; n++ )
+    {
+     curlen  = nextlen;
+     nextlen = tree[n+1].dl.len;
+
+     if (++count < max_count && curlen == nextlen)
+       {
+        continue;
+       }
+     else if (count < min_count)
+       {
+        do { send_code(curlen, gz1->bl_tree); } while (--count != 0);
+       }
+     else if (curlen != 0)
+       {
+        if ( curlen != prevlen )
+          {
+           send_code(curlen, gz1->bl_tree); count--;
+          }
+
+        send_code( REP_3_6, gz1->bl_tree ); send_bits(gz1,count-3, 2);
+       }
+     else if (count <= 10)
+       {
+        send_code(REPZ_3_10, gz1->bl_tree); send_bits(gz1,count-3, 3);
+       }
+     else
+       {
+        send_code(REPZ_11_138, gz1->bl_tree); send_bits(gz1,count-11, 7);
+       }
+
+     count   = 0;
+     prevlen = curlen;
+
+     if (nextlen == 0)
+       {
+        max_count = 138, min_count = 3;
+       }
+     else if (curlen == nextlen)
+       {
+        max_count = 6, min_count = 3;
+       }
+     else
+       {
+        max_count = 7, min_count = 4;
+       }
+    }
+}
+
+void scan_tree(
+PGZ1     gz1,     
+ct_data *tree,    
+int      max_code 
+)
+{
+ int n;                        
+ int prevlen = -1;             
+ int curlen;                   
+ int nextlen = tree[0].dl.len; 
+ int count = 0;                
+ int max_count = 7;            
+ int min_count = 4;            
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ tree[max_code+1].dl.len = (ush)0xffff; 
+
+ for ( n = 0; n <= max_code; n++ )
+    {
+     curlen  = nextlen;
+     nextlen = tree[n+1].dl.len;
+
+     if ( ++count < max_count && curlen == nextlen )
+       {
+        continue;
+       }
+     else if ( count < min_count )
+       {
+        gz1->bl_tree[curlen].fc.freq += count;
+       }
+     else if ( curlen != 0 )
+       {
+        if ( curlen != prevlen ) gz1->bl_tree[curlen].fc.freq++;
+        gz1->bl_tree[REP_3_6].fc.freq++;
+       }
+     else if ( count <= 10 )
+       {
+        gz1->bl_tree[REPZ_3_10].fc.freq++;
+       }
+     else
+       {
+        gz1->bl_tree[REPZ_11_138].fc.freq++;
+       }
+
+     count   = 0;
+     prevlen = curlen;
+
+     if ( nextlen == 0 )
+       {
+        max_count = 138;
+        min_count = 3;
+       }
+     else if (curlen == nextlen)
+       {
+        max_count = 6;
+        min_count = 3;
+       }
+     else
+       {
+        max_count = 7;
+        min_count = 4;
+       }
+    }
+}
+
+void pqdownheap(
+PGZ1     gz1,  
+ct_data *tree, 
+int      k     
+)
+{
+ int v = gz1->heap[k];
+ int j = k << 1;  
+
+ while( j <= gz1->heap_len )
+   {
+    if (j < gz1->heap_len && smaller(tree, gz1->heap[j+1], gz1->heap[j])) j++;
+
+    if (smaller(tree, v, gz1->heap[j])) break;
+
+    gz1->heap[k] = gz1->heap[j];  k = j;
+
+    j <<= 1;
+   }
+
+ gz1->heap[k] = v;
+}
+
+
+#define GZS_ZIP1      1
+#define GZS_ZIP2      2
+#define GZS_DEFLATE1  3
+#define GZS_DEFLATE2  4
+
+int gzs_fsp     ( PGZ1 gz1 ); 
+int gzs_zip1    ( PGZ1 gz1 ); 
+int gzs_zip2    ( PGZ1 gz1 ); 
+int gzs_deflate1( PGZ1 gz1 ); 
+int gzs_deflate2( PGZ1 gz1 ); 
+
+int gzp_main( GZP_CONTROL *gzp )
+{
+ PGZ1 gz1 = 0; 
+ int  rc  = 0;
+ int  final_exit_code = 0;
+ int  ofile_flags = O_RDWR | O_CREAT | O_TRUNC | O_BINARY;
+
+ gzp->result_code = 0; 
+ gzp->bytes_out   = 0; 
+
+ gz1 = (PGZ1) gz1_init();
+
+ if ( gz1 == 0 )
+   {
+    return 0;
+   }
+
+ gz1->decompress      = gzp->decompress;
+ gz1->compression_format = gzp->compression_format;
+
+ strcpy( gz1->ifname, gzp->input_filename  );
+ strcpy( gz1->ofname, gzp->output_filename );
+
+ gz1->input_ismem     = gzp->input_ismem;
+ gz1->input_ptr       = gzp->input_ismem_ibuf;
+ gz1->input_bytesleft = gzp->input_ismem_ibuflen;
+
+ gz1->output_ismem    = gzp->output_ismem;
+ gz1->output_ptr      = gzp->output_ismem_obuf;
+ gz1->output_maxlen   = gzp->output_ismem_obuflen;
+
+ if ( gz1->no_time < 0 ) gz1->no_time = gz1->decompress;
+ if ( gz1->no_name < 0 ) gz1->no_name = gz1->decompress;
+
+ work = zip; 
+
+ if ( !gz1->input_ismem ) 
+   {
+    errno = 0;
+
+    rc = stat( gz1->ifname, &gz1->istat );
+
+    if ( rc != 0 ) 
+      {
+       gz1_cleanup( gz1 ); 
+
+       return 0; 
+      }
+
+    gz1->ifile_size = gz1->istat.st_size;
+
+    gz1->ifd =
+    OPEN(
+    gz1->ifname,
+    gz1->ascii && !gz1->decompress ? O_RDONLY : O_RDONLY | O_BINARY,
+    RW_USER
+    );
+
+    if ( gz1->ifd == -1 )
+      {
+       gz1_cleanup( gz1 ); 
+
+       return 0; 
+      }
+   }
+
+ if ( !gz1->output_ismem ) 
+   {
+    if ( gz1->ascii && gz1->decompress )
+      {
+       ofile_flags &= ~O_BINARY; 
+      }
+
+    gz1->ofd = OPEN( gz1->ofname, ofile_flags, RW_USER );
+
+    if ( gz1->ofd == -1 )
+      {
+       if ( gz1->ifd ) 
+         {
+          close( gz1->ifd ); 
+          gz1->ifd = 0;      
+         }
+
+       gz1_cleanup( gz1 ); 
+
+       return 0; 
+      }
+   }
+
+ gz1->outcnt    = 0;
+ gz1->insize    = 0;
+ gz1->inptr     = 0;
+ gz1->bytes_in  = 0L;
+ gz1->bytes_out = 0L; 
+ gz1->part_nb   = 0;
+
+ if ( gz1->decompress )
+   {
+    gz1->method = get_header( gz1, gz1->ifd );
+
+    if ( gz1->method < 0 )
+      {
+       if ( gz1->ifd ) 
+         {
+          close( gz1->ifd ); 
+          gz1->ifd = 0;      
+         }
+
+       if ( gz1->ofd ) 
+         {
+          close( gz1->ofd ); 
+          gz1->ofd = 0;      
+         }
+
+       return 0; 
+      }
+   }
+
+ gz1->save_orig_name = 0;
+
+ gz1->state = GZS_ZIP1;
+
+ for (;;) 
+    {
+     gzs_fsp( gz1 ); 
+
+     if ( gz1->done == 1 ) break; 
+    }
+
+ if ( gz1->ifd ) 
+   {
+    close( gz1->ifd ); 
+    gz1->ifd = 0;      
+   }
+
+ if ( gz1->ofd ) 
+   {
+    close( gz1->ofd ); 
+    gz1->ofd = 0;      
+   }
+
+ gzp->result_code = gz1->exit_code;
+ gzp->bytes_out   = gz1->bytes_out;
+
+ final_exit_code = (int) gz1->exit_code;
+
+ gz1_cleanup( gz1 );  
+
+ return final_exit_code; 
+}
+
+int gzs_fsp( PGZ1 gz1 )
+{
+ int rc=0; 
+
+ switch( gz1->state )
+   {
+    case GZS_ZIP1:
+
+         rc = gzs_zip1( gz1 );
+
+         break;
+
+    case GZS_ZIP2:
+
+         rc = gzs_zip2( gz1 );
+
+         break;
+
+    case GZS_DEFLATE1:
+
+         rc = gzs_deflate1( gz1 );
+
+         break;
+
+    case GZS_DEFLATE2:
+
+         rc = gzs_deflate2( gz1 );
+
+         break;
+
+    default: 
+
+         gz1->done = 1;
+
+         break;
+   }
+
+ return( rc );
+}
+
+
+int gzs_zip1( PGZ1 gz1 )
+{
+ uch  flags = 0;         
+ ush  attr  = 0;         
+ ush  deflate_flags = 0; 
+
+ gz1->outcnt = 0;
+
+ gz1->method = DEFLATED;
+
+ if (gz1->compression_format != DEFLATE_FORMAT)
+   {
+    put_byte(GZIP_MAGIC[0]); 
+    put_byte(GZIP_MAGIC[1]);
+    put_byte(DEFLATED);      
+   }
+ else
+   {
+       /* Yes, I know RFC 1951 doesn't mention any header at the start of
+        * a deflated document, but zlib absolutely requires one. And since nearly
+     * all "deflate" implementations use zlib, we need to play along with this
+     * brain damage. */
+    put_byte(ZLIB_HEADER[0]); 
+    put_byte(ZLIB_HEADER[1]);
+   }
+
+ if ( gz1->save_orig_name )
+   {
+       flags |= ORIG_NAME;
+   }
+
+ if (gz1->compression_format != DEFLATE_FORMAT)
+   {
+    put_byte(flags);           
+    put_long(gz1->time_stamp); 
+
+       gz1->crc = -1; 
+    updcrc( gz1, NULL, 0 ); 
+   }
+ else
+   {
+       /* Deflate compression uses an Adler32 CRC, not a CRC32. */
+       gz1->adler = 1L;
+   }
+
+ gz1->state = GZS_ZIP2;
+
+ return 0;
+}
+
+int gzs_zip2( PGZ1 gz1 )
+{
+ uch  flags = 0;         
+ ush  attr  = 0;         
+ ush  deflate_flags = 0; 
+
+ bi_init( gz1, gz1->ofd );
+ ct_init( gz1, &attr, &gz1->method );
+ lm_init( gz1, gz1->level, &deflate_flags );
+
+ if (gz1->compression_format != DEFLATE_FORMAT)
+   {
+    put_byte((uch)deflate_flags); 
+    put_byte(OS_CODE); 
+    if ( gz1->save_orig_name )
+      {
+       char *p = gz1_basename( gz1, gz1->ifname );
+
+       do {
+              put_char(*p);
+
+          } while (*p++);
+      }
+   }
+
+ gz1->header_bytes = (long)gz1->outcnt;
+
+ gz1->state = GZS_DEFLATE1;
+
+ return 0;
+}
+
+int gzs_deflate1( PGZ1 gz1 )
+{
+ if ( !gz1->deflate1_initialized )
+   {
+    gz1->deflate1_match_available = 0;           
+    gz1->deflate1_match_length    = MIN_MATCH-1; 
+    gz1->deflate1_initialized     = 1;
+   }
+
+ if ( gz1->compr_level <= 3 )
+   {
+    gz1->done = 1; 
+
+    return 0;
+   }
+
+ if ( gz1->lookahead == 0 )
+   {
+    if ( gz1->deflate1_match_available )
+      {
+       ct_tally( gz1, 0, gz1->window[gz1->strstart-1] );
+      }
+
+    gz1->state = GZS_DEFLATE2;
+
+    return (int) FLUSH_BLOCK(1); 
+   }
+
+ #ifdef STAY_HERE_FOR_A_CERTAIN_AMOUNT_OF_ITERATIONS
+ while( iterations < max_iterations_per_yield )
+   {
+ #endif
+
+    gz1->ins_h =
+    (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[gz1->strstart+MIN_MATCH-1])) & HASH_MASK;
+
+    prev[ gz1->strstart & WMASK ] = gz1->deflate1_hash_head = head[ gz1->ins_h ];
+
+    head[ gz1->ins_h ] = gz1->strstart;
+
+    gz1->prev_length = gz1->deflate1_match_length, gz1->deflate1_prev_match = gz1->match_start;
+    gz1->deflate1_match_length = MIN_MATCH-1;
+
+    if ( gz1->deflate1_hash_head != NIL && gz1->prev_length < gz1->max_lazy_match &&
+         gz1->strstart - gz1->deflate1_hash_head <= MAX_DIST)
+      {
+       gz1->deflate1_match_length = longest_match( gz1, gz1->deflate1_hash_head );
+
+       if ( gz1->deflate1_match_length > gz1->lookahead )
+         {
+          gz1->deflate1_match_length = gz1->lookahead;
+         }
+
+       if (gz1->deflate1_match_length == MIN_MATCH && gz1->strstart-gz1->match_start > TOO_FAR)
+         {
+          gz1->deflate1_match_length--;
+         }
+      }
+
+    if ( gz1->prev_length >= MIN_MATCH && gz1->deflate1_match_length <= gz1->prev_length )
+      {
+       gz1->deflate1_flush =
+       ct_tally(gz1,gz1->strstart-1-gz1->deflate1_prev_match, gz1->prev_length - MIN_MATCH);
+
+       gz1->lookahead   -= ( gz1->prev_length - 1 );
+       gz1->prev_length -= 2;
+
+       do {
+           gz1->strstart++;
+
+           gz1->ins_h =
+           (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK;
+
+           prev[ gz1->strstart & WMASK ] = gz1->deflate1_hash_head = head[gz1->ins_h];
+
+           head[ gz1->ins_h ] = gz1->strstart;
+
+          } while (--gz1->prev_length != 0);
+
+       gz1->deflate1_match_available = 0;
+       gz1->deflate1_match_length    = MIN_MATCH-1;
+
+       gz1->strstart++;
+
+       if (gz1->deflate1_flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
+      }
+
+    else
+      {
+       if ( gz1->deflate1_match_available )
+         {
+          if ( ct_tally( gz1, 0, gz1->window[gz1->strstart-1] ) )
+            {
+             FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
+            }
+
+          gz1->strstart++;
+          gz1->lookahead--;
+         }
+       else 
+         {
+          gz1->deflate1_match_available = 1;
+          gz1->strstart++;
+          gz1->lookahead--;
+         }
+
+       while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile )
+         {
+          fill_window(gz1);
+         }
+      }
+
+ return 0;
+}
+
+int gzs_deflate2( PGZ1 gz1 )
+{
+ #if !defined(NO_SIZE_CHECK) && !defined(RECORD_IO)
+ if (gz1->ifile_size != -1L && gz1->isize != (ulg)gz1->ifile_size)
+   {
+   }
+ #endif
+
+ if (gz1->compression_format != DEFLATE_FORMAT)
+   {
+    put_long( gz1->crc );
+    put_long( gz1->bytes_in );
+    gz1->header_bytes += 2*sizeof(long);
+   }
+ else
+   {
+       /* Append an Adler32 CRC to our deflated data.
+        * Yes, I know RFC 1951 doesn't mention any CRC at the end of a
+        * deflated document, but zlib absolutely requires one. And since nearly
+        * all "deflate" implementations use zlib, we need to play along with this
+        * brain damage. */
+       put_byte( (gz1->adler >> 24)        );
+       put_byte( (gz1->adler >> 16) & 0xFF );
+       put_byte( (gz1->adler >>  8) & 0xFF );
+       put_byte( (gz1->adler      ) & 0xFF );
+    gz1->header_bytes += 4*sizeof(uch);
+   }
+
+ flush_outbuf( gz1 );
+
+ gz1->done = 1; 
+
+ return OK;
+}
+
+
+/* =========================================================================
+   adler32 -- compute the Adler-32 checksum of a data stream
+   Copyright (C) 1995-1998 Mark Adler
+
+   This software is provided 'as-is', without any express or implied
+   warranty.  In no event will the authors be held liable for any damages
+   arising from the use of this software.
+
+   Permission is granted to anyone to use this software for any purpose,
+   including commercial applications, and to alter it and redistribute it
+   freely, subject to the following restrictions:
+
+   1. The origin of this software must not be misrepresented; you must not
+      claim that you wrote the original software. If you use this software
+      in a product, an acknowledgment in the product documentation would be
+      appreciated but is not required.
+   2. Altered source versions must be plainly marked as such, and must not be
+      misrepresented as being the original software.
+   3. This notice may not be removed or altered from any source distribution.
+
+   Modified by Eric Kidd <eric.kidd@pobox.com> to play nicely with mod_gzip.
+ */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+ulg adler32(ulg adler, uch *buf, unsigned len)
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+           buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+           s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
+
+
+/* END OF FILE */
+
+
diff --git a/tools/turbocharger/mod_gzip.c.diff b/tools/turbocharger/mod_gzip.c.diff
new file mode 100644 (file)
index 0000000..a2c5000
--- /dev/null
@@ -0,0 +1,365 @@
+--- mod_gzip.c-old     Fri Jan 26 10:50:05 2001
++++ mod_gzip.c Fri Jan 26 15:08:26 2001
+@@ -575,10 +575,15 @@
+  * The GZP request control structure...
+  */
++#define GZIP_FORMAT    (0)
++#define DEFLATE_FORMAT (1)
++
+ typedef struct _GZP_CONTROL {
+     int   decompress;  /* 0=Compress 1=Decompress */
++    int   compression_format;  /* GZIP_FORMAT or DEFLATE_FORMAT */
++
+     /* Input control... */
+     int   input_ismem;         /* Input source is memory buffer, not file */
+@@ -2209,10 +2214,11 @@
+        mod_gzip_printf( "%s: Checking for 'gzip' designator...\n",cn);
+        #endif
+-       if ( strstr( has_encoding, "gzip" ) )
++       if ( strstr( has_encoding, "gzip" ) ||
++                      strstr( has_encoding, "deflate" ) )
+          {
+           #ifdef MOD_GZIP_DEBUG1
+-          mod_gzip_printf( "%s: 'Content-encoding:' field contains 'gzip' designator...\n",cn);
++          mod_gzip_printf( "%s: 'Content-encoding:' field contains 'gzip' or 'deflate' designator...\n",cn);
+           mod_gzip_printf( "%s: Pre-compression is assumed.\n",cn);
+           mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
+           #endif
+@@ -2237,7 +2243,7 @@
+        else /* 'gzip' designator not found... */
+          {
+           #ifdef MOD_GZIP_DEBUG1
+-          mod_gzip_printf( "%s: 'Content-encoding:' field does NOT contain 'gzip' designator...\n",cn);
++          mod_gzip_printf( "%s: 'Content-encoding:' field does NOT contain 'gzip' or 'deflate' designator...\n",cn);
+           mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
+           #endif
+          }
+@@ -2347,10 +2353,21 @@
+     if ( accept_encoding )
+       {
+        /* ...and if it has the right 'gzip' indicator... */
+-
++         /* We record the compression format in a request note, so we
++        * can get it again later, and so it can potentially be logged.
++        */
+        if ( strstr( accept_encoding, "gzip" ) )
+          {
+           process = 1; /* ...set the 'process' flag TRUE */
++          ap_table_setn( r->notes,"mod_gzip_compression_format",
++                                               ap_pstrdup(r->pool,"gzip"));
++
++         }
++       else if ( strstr( accept_encoding, "deflate" ) )
++         {
++          process = 1; /* ...set the 'process' flag TRUE */
++          ap_table_setn( r->notes,"mod_gzip_compression_format",
++                                               ap_pstrdup(r->pool,"deflate"));
+          }
+       }/* End 'if( accept_encoding )' */
+@@ -2388,7 +2405,7 @@
+     else /* 'gzip' designator was seen in 'Accept-Encoding:' field */
+       {
+        #ifdef MOD_GZIP_DEBUG1
+-       mod_gzip_printf( "%s: 'gzip' capability specified by user-agent.\n",cn);
++       mod_gzip_printf( "%s: 'gzip' or 'deflate' capability specified by user-agent.\n",cn);
+        mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
+        #endif
+       }
+@@ -4093,7 +4110,8 @@
+     char tmp[ MOD_GZIP_LARGE_BUFFER_SIZE + 2 ]; /* Scratch buffer */
+-    char actual_content_encoding_name[] = "gzip"; /* Adjustable */
++    char *actual_content_encoding_name = "gzip"; /* Adjustable */
++      const char *compression_format;
+     #ifdef MOD_GZIP_DEBUG1
+     char cn[]="mod_gzip_encode_and_transmit()";
+@@ -4470,6 +4488,18 @@
+     gzp->decompress = 0; /* Perform encoding */
++      /* Recover the compression format we're supposed to use. */
++      compression_format = ap_table_get(r->notes, "mod_gzip_compression_format");
++      if (compression_format && strcmp(compression_format, "deflate") == 0)
++        {
++         actual_content_encoding_name = "deflate";
++         gzp->compression_format = DEFLATE_FORMAT;
++      }
++    else
++        {
++         gzp->compression_format = GZIP_FORMAT;
++      }
++
+     if ( input_size <= (long) conf->maximum_inmem_size )
+       {
+        /* The input source is small enough to compress directly */
+@@ -4591,6 +4621,7 @@
+     #ifdef MOD_GZIP_DEBUG1
+     mod_gzip_printf( "%s: gzp->decompress      = %d\n"  ,cn,gzp->decompress);
++    mod_gzip_printf( "%s: gzp->compression_format = %d\n",cn,gzp->compression_format);
+     mod_gzip_printf( "%s: gzp->input_ismem     = %d\n",  cn,gzp->input_ismem);
+     mod_gzip_printf( "%s: gzp->output_ismem    = %d\n",  cn,gzp->output_ismem);
+     mod_gzip_printf( "%s: gzp->input_filename  = [%s]\n",cn,gzp->input_filename);
+@@ -7256,6 +7287,8 @@
+ };
+ typedef struct _GZ1 {
++ long     compression_format;
++
+  long     versionid1;
+  int      state;
+  int      done;
+@@ -7345,6 +7378,7 @@
+  int  dbits;            
+  ulg  window_size;      
+  ulg  crc;              
++ ulg  adler;
+  uch  dist_code[512];
+  uch  length_code[MAX_MATCH-MIN_MATCH+1];
+@@ -7449,6 +7483,15 @@
+ void  error( char *msg   );
++/* XXX - Precomputed zlib header. If you change the window size or
++ * compression level from the defaults, this will break badly. The
++ * algorithm to build this is fairly complex; you can find it in
++ * the file deflate.c from the zlib distribution.
++ */
++#define ZLIB_HEADER "\170\9c"
++
++ulg adler32(ulg adler, uch *buf, unsigned len);
++
+ int zip(
+ PGZ1 gz1, 
+ int  in,  
+@@ -9088,10 +9131,20 @@
+  if ( len == (unsigned)(-1) || len == 0 )
+    {
+       gz1->crc = gz1->crc ^ 0xffffffffL;
++    /* XXX - Do we need to do something with Adler CRC's here?
++       * I don't think so--they don't seem to need postprocessing. */
+     return (int)len;
+    }
+- updcrc( gz1, (uch*)buf, len );
++ if (gz1->compression_format != DEFLATE_FORMAT)
++   {
++    updcrc( gz1, (uch*)buf, len );
++   }
++ else
++   {
++      gz1->adler = adler32(gz1->adler, (uch*)buf, len);
++   }
++
+  gz1->bytes_in += (ulg)len;
+  return (int)len;
+@@ -9288,6 +9341,7 @@
+  gz1->heap[k] = v;
+ }
++
+ #define GZS_ZIP1      1
+ #define GZS_ZIP2      2
+ #define GZS_DEFLATE1  3
+@@ -9317,6 +9371,7 @@
+    }
+  gz1->decompress      = gzp->decompress;
++ gz1->compression_format = gzp->compression_format;
+  strcpy( gz1->ifname, gzp->input_filename  );
+  strcpy( gz1->ofname, gzp->output_filename );
+@@ -9489,6 +9544,7 @@
+  return( rc );
+ }
++
+ int gzs_zip1( PGZ1 gz1 )
+ {
+  uch  flags = 0;         
+@@ -9499,21 +9555,40 @@
+  gz1->method = DEFLATED;
+- put_byte(GZIP_MAGIC[0]); 
+- put_byte(GZIP_MAGIC[1]);
+- put_byte(DEFLATED);      
++ if (gz1->compression_format != DEFLATE_FORMAT)
++   {
++    put_byte(GZIP_MAGIC[0]); 
++    put_byte(GZIP_MAGIC[1]);
++    put_byte(DEFLATED);      
++   }
++ else
++   {
++      /* Yes, I know RFC 1951 doesn't mention any header at the start of
++       * a deflated document, but zlib absolutely requires one. And since nearly
++     * all "deflate" implementations use zlib, we need to play along with this
++     * brain damage. */
++    put_byte(ZLIB_HEADER[0]); 
++    put_byte(ZLIB_HEADER[1]);
++   }
+  if ( gz1->save_orig_name )
+    {
+       flags |= ORIG_NAME;
+    }
+- put_byte(flags);           
+- put_long(gz1->time_stamp); 
+-
+- gz1->crc = -1; 
++ if (gz1->compression_format != DEFLATE_FORMAT)
++   {
++    put_byte(flags);           
++    put_long(gz1->time_stamp); 
+- updcrc( gz1, NULL, 0 ); 
++      gz1->crc = -1; 
++    updcrc( gz1, NULL, 0 ); 
++   }
++ else
++   {
++      /* Deflate compression uses an Adler32 CRC, not a CRC32. */
++      gz1->adler = 1L;
++   }
+  gz1->state = GZS_ZIP2;
+@@ -9529,18 +9604,20 @@
+  bi_init( gz1, gz1->ofd );
+  ct_init( gz1, &attr, &gz1->method );
+  lm_init( gz1, gz1->level, &deflate_flags );
+- put_byte((uch)deflate_flags); 
+-
+- put_byte(OS_CODE); 
+- if ( gz1->save_orig_name )
++ if (gz1->compression_format != DEFLATE_FORMAT)
+    {
+-    char *p = gz1_basename( gz1, gz1->ifname );
++    put_byte((uch)deflate_flags); 
++    put_byte(OS_CODE); 
++    if ( gz1->save_orig_name )
++      {
++       char *p = gz1_basename( gz1, gz1->ifname );
+-    do {
+-          put_char(*p);
++       do {
++             put_char(*p);
+-       } while (*p++);
++          } while (*p++);
++      }
+    }
+  gz1->header_bytes = (long)gz1->outcnt;
+@@ -9674,10 +9751,25 @@
+    }
+  #endif
+- put_long( gz1->crc      );
+- put_long( gz1->bytes_in );
+-
+- gz1->header_bytes += 2*sizeof(long);
++ if (gz1->compression_format != DEFLATE_FORMAT)
++   {
++    put_long( gz1->crc );
++    put_long( gz1->bytes_in );
++    gz1->header_bytes += 2*sizeof(long);
++   }
++ else
++   {
++      /* Append an Adler32 CRC to our deflated data.
++       * Yes, I know RFC 1951 doesn't mention any CRC at the end of a
++       * deflated document, but zlib absolutely requires one. And since nearly
++       * all "deflate" implementations use zlib, we need to play along with this
++       * brain damage. */
++      put_byte( (gz1->adler >> 24)        );
++      put_byte( (gz1->adler >> 16) & 0xFF );
++      put_byte( (gz1->adler >>  8) & 0xFF );
++      put_byte( (gz1->adler      ) & 0xFF );
++    gz1->header_bytes += 4*sizeof(uch);
++   }
+  flush_outbuf( gz1 );
+@@ -9685,6 +9777,67 @@
+  return OK;
+ }
++
++
++/* =========================================================================
++   adler32 -- compute the Adler-32 checksum of a data stream
++   Copyright (C) 1995-1998 Mark Adler
++
++   This software is provided 'as-is', without any express or implied
++   warranty.  In no event will the authors be held liable for any damages
++   arising from the use of this software.
++
++   Permission is granted to anyone to use this software for any purpose,
++   including commercial applications, and to alter it and redistribute it
++   freely, subject to the following restrictions:
++
++   1. The origin of this software must not be misrepresented; you must not
++      claim that you wrote the original software. If you use this software
++      in a product, an acknowledgment in the product documentation would be
++      appreciated but is not required.
++   2. Altered source versions must be plainly marked as such, and must not be
++      misrepresented as being the original software.
++   3. This notice may not be removed or altered from any source distribution.
++
++   Modified by Eric Kidd <eric.kidd@pobox.com> to play nicely with mod_gzip.
++ */
++
++#define BASE 65521L /* largest prime smaller than 65536 */
++#define NMAX 5552
++/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
++
++#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
++#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
++#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
++#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
++#define DO16(buf)   DO8(buf,0); DO8(buf,8);
++
++ulg adler32(ulg adler, uch *buf, unsigned len)
++{
++    unsigned long s1 = adler & 0xffff;
++    unsigned long s2 = (adler >> 16) & 0xffff;
++    int k;
++
++    if (buf == NULL) return 1L;
++
++    while (len > 0) {
++        k = len < NMAX ? len : NMAX;
++        len -= k;
++        while (k >= 16) {
++            DO16(buf);
++          buf += 16;
++            k -= 16;
++        }
++        if (k != 0) do {
++            s1 += *buf++;
++          s2 += s1;
++        } while (--k);
++        s1 %= BASE;
++        s2 %= BASE;
++    }
++    return (s2 << 16) | s1;
++}
++
+ /* END OF FILE */
diff --git a/tools/xml-rpc-api2cpp/.cvsignore b/tools/xml-rpc-api2cpp/.cvsignore
new file mode 100644 (file)
index 0000000..c194ee8
--- /dev/null
@@ -0,0 +1 @@
+xml-rpc-api2cpp
diff --git a/tools/xml-rpc-api2cpp/DataType.cpp b/tools/xml-rpc-api2cpp/DataType.cpp
new file mode 100644 (file)
index 0000000..59854ba
--- /dev/null
@@ -0,0 +1,195 @@
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+#include "xmlrpc-c/oldcppwrapper.hpp"
+#include "DataType.hpp"
+
+using namespace std;
+
+
+
+//=========================================================================
+//  abstract class DataType
+//=========================================================================
+//  Instances of DataType know how generate code fragments for manipulating
+//  a specific XML-RPC data type.
+
+string DataType::defaultParameterBaseName (int position) const {
+    ostringstream name_stream;
+    name_stream << typeName() << position << ends;
+    string name(name_stream.str());
+    return name;
+}
+
+
+//=========================================================================
+//  class RawDataType
+//=========================================================================
+//  We want to manipulate some XML-RPC data types as XmlRpcValue objects.
+
+class RawDataType : public DataType {
+public:
+    RawDataType (const string& type_name) : DataType(type_name) {}
+    
+    virtual string parameterFragment (const string& base_name) const;
+    virtual string inputConversionFragment (const string& base_name) const;
+    virtual string returnTypeFragment () const;
+    virtual string outputConversionFragment (const string& var_name) const;
+};
+
+string RawDataType::parameterFragment (const string& base_name) const {
+    return "XmlRpcValue /*" + typeName() + "*/ " + base_name;
+}
+
+string RawDataType::inputConversionFragment (const string& base_name) const {
+    return base_name;
+}
+
+string RawDataType::returnTypeFragment () const {
+    return "XmlRpcValue /*" + typeName() + "*/";
+}
+
+string RawDataType::outputConversionFragment (const string& var_name) const {
+    return var_name;
+}
+
+
+//=========================================================================
+//  class SimpleDataType
+//=========================================================================
+//  Other types can be easily converted to and from a single native type.
+
+class SimpleDataType : public DataType {
+    string mNativeType;
+    string mMakerFunc;
+    string mGetterFunc;
+
+public:
+    SimpleDataType (const string& type_name,
+                   const string& native_type,
+                   const string& maker_func,
+                   const string& getter_func);
+
+    virtual string parameterFragment (const string& base_name) const;
+    virtual string inputConversionFragment (const string& base_name) const;
+    virtual string returnTypeFragment () const;
+    virtual string outputConversionFragment (const string& var_name) const;
+};
+
+SimpleDataType::SimpleDataType (const string& type_name,
+                               const string& native_type,
+                               const string& maker_func,
+                               const string& getter_func)
+    : DataType(type_name),
+      mNativeType(native_type),
+      mMakerFunc(maker_func),
+      mGetterFunc(getter_func)
+{
+}
+
+string SimpleDataType::parameterFragment (const string& base_name) const {
+    return mNativeType + " " + base_name;
+}
+
+string SimpleDataType::inputConversionFragment (const string& base_name) const
+{
+    return mMakerFunc + "(" + base_name + ")";
+}
+
+string SimpleDataType::returnTypeFragment () const {
+    return mNativeType; 
+}
+
+string SimpleDataType::outputConversionFragment (const string& var_name) const
+{
+    return var_name + "." + mGetterFunc + "()";
+}
+
+
+//=========================================================================
+//  class VoidDataType
+//=========================================================================
+//  Some XML-RPC servers declare functions as void.  Such functions have
+//  an arbitrary return value which we should ignore.
+
+class VoidDataType : public DataType {
+public:
+    VoidDataType () : DataType("void") {}
+    
+    virtual string parameterFragment (const string& base_name) const;
+    virtual string inputConversionFragment (const string& base_name) const;
+    virtual string returnTypeFragment () const;
+    virtual string outputConversionFragment (const string& var_name) const;
+};
+
+string VoidDataType::parameterFragment (const string&) const {
+    throw domain_error("Can't handle functions with 'void' arguments'");
+    
+}
+
+string VoidDataType::inputConversionFragment (const string&) const {
+    throw domain_error("Can't handle functions with 'void' arguments'");
+}
+
+string VoidDataType::returnTypeFragment () const {
+    return "void";
+}
+
+string VoidDataType::outputConversionFragment (const string&) const {
+    return "/* Return value ignored. */";
+}
+
+
+//=========================================================================
+//  function findDataType
+//=========================================================================
+//  Given the name of an XML-RPC data type, try to find a corresponding
+//  DataType object.
+
+SimpleDataType intType    ("int", "XmlRpcValue::int32",
+                          "XmlRpcValue::makeInt",
+                          "getInt");
+SimpleDataType boolType   ("bool", "bool",
+                          "XmlRpcValue::makeBool",
+                          "getBool");
+SimpleDataType doubleType ("double", "double",
+                          "XmlRpcValue::makeDouble",
+                          "getDouble");
+SimpleDataType stringType ("string", "string",
+                          "XmlRpcValue::makeString",
+                          "getString");
+
+RawDataType dateTimeType  ("dateTime");
+RawDataType base64Type    ("base64");
+RawDataType structType    ("struct");
+RawDataType arrayType     ("array");
+
+VoidDataType voidType;
+
+const DataType& findDataType (const string& name) {
+    if (name == "int" || name == "i4")
+       return intType;
+    else if (name == "boolean")
+       return boolType;
+    else if (name == "double")
+       return doubleType;
+    else if (name == "string")
+       return stringType;
+    else if (name == "dateTime.iso8601")
+       return dateTimeType;
+    else if (name == "base64")
+       return base64Type;
+    else if (name == "struct")
+       return structType;
+    else if (name == "array")
+       return arrayType;
+    else if (name == "void")
+       return voidType;
+    else
+       throw domain_error("Unknown XML-RPC type " + name);
+    
+    // This code should never be executed.
+    XMLRPC_ASSERT(0);
+    return intType;
+}
diff --git a/tools/xml-rpc-api2cpp/DataType.hpp b/tools/xml-rpc-api2cpp/DataType.hpp
new file mode 100644 (file)
index 0000000..b5cab35
--- /dev/null
@@ -0,0 +1,43 @@
+#include <string>
+#include <cassert>
+
+class DataType {
+    std::string mTypeName;
+
+    DataType(DataType const&) { assert(false); }
+    
+    DataType& operator= (DataType const&) {
+        assert(false);
+        return *this;
+    }
+
+public:
+    DataType(const std::string& type_name) : mTypeName(type_name) {}
+
+    virtual ~DataType () {}
+
+    // Return the name for this XML-RPC type.
+    virtual std::string
+    typeName() const { return mTypeName; }
+
+    // Given a parameter position, calculate a unique base name for all
+    // parameter-related variables.
+    virtual std::string
+    defaultParameterBaseName(int position) const;
+
+    // Virtual functions for processing parameters.
+    virtual std::string
+    parameterFragment(std::string const& base_name) const = 0;
+
+    virtual std::string
+    inputConversionFragment(std::string const& base_name) const = 0;
+
+    // Virtual functions for processing return values.
+    virtual std::string
+    returnTypeFragment () const = 0;
+
+    virtual std::string
+    outputConversionFragment(std::string const& var_name) const = 0;
+};
+
+const DataType& findDataType(const std::string& name);
diff --git a/tools/xml-rpc-api2cpp/Makefile b/tools/xml-rpc-api2cpp/Makefile
new file mode 100644 (file)
index 0000000..e857094
--- /dev/null
@@ -0,0 +1,67 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+# BLDDIR is for use in places where a symbolic link won't work.
+# BUILDDIR is for places in Makefile.common that can use the 'blddir'
+# symbolic link (but in other directories, doesn't).
+BLDDIR = $(SRCDIR)
+BUILDDIR = blddir
+
+default: all
+
+include $(BLDDIR)/Makefile.config
+
+include ../Makefile.common
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include
+
+CXXFLAGS = $(INCLUDES) $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
+
+LDFLAGS = $(LADD)
+
+LDLIBS = -Lblddir/src/cpp -lxmlrpc_cpp -lxmlrpc_server $(CLIENT_LDLIBS)
+
+PROGS :=
+
+ifeq ($(MUST_BUILD_CLIENT),yes)
+  PROGS += xml-rpc-api2cpp
+endif
+
+all: $(PROGS)
+
+OBJECTS = \
+  xml-rpc-api2cpp.o \
+  DataType.o \
+  XmlRpcFunction.o \
+  XmlRpcClass.o \
+  SystemProxy.o \
+
+xml-rpc-api2cpp: \
+  $(OBJECTS) \
+  $(LIBXMLRPC_CPP) \
+  $(LIBXMLRPC_CLIENT) \
+  $(LIBXMLRPC_SERVER) \
+  $(LIBXMLRPC) \
+  $(LIBXMLRPC_XML) \
+  $(LIBXMLRPC_UTIL)
+       $(CXXLD) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS)
+
+%.o:%.cpp
+       $(CXX) -c $(CXXFLAGS) $<
+
+# This Makefile.config dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(BLDDIR)/Makefile.config: blddir srcdir
+
+include Makefile.depend
+
+.PHONY: clean
+clean: clean-common
+       rm -f xml-rpc-api2cpp
+
+.PHONY: distclean
+distclean: clean distclean-common
+
+.PHONY: dep
+dep: dep-common
diff --git a/tools/xml-rpc-api2cpp/Makefile.depend b/tools/xml-rpc-api2cpp/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/xml-rpc-api2cpp/README b/tools/xml-rpc-api2cpp/README
new file mode 100644 (file)
index 0000000..4dff2a3
--- /dev/null
@@ -0,0 +1,6 @@
+This program generates C++ wrapper classes for XML-RPC servers.  It talks
+to xmlrpc-c and XML-RPC.NET servers without any problems, but tends to
+choke when talking to mod_php-based servers.  It looks like there is some
+kind of pipelining problem.
+
+This code is an ongoing project.  Please send feedback!
diff --git a/tools/xml-rpc-api2cpp/SystemProxy.cpp b/tools/xml-rpc-api2cpp/SystemProxy.cpp
new file mode 100644 (file)
index 0000000..f24fadc
--- /dev/null
@@ -0,0 +1,39 @@
+// SystemProxy.cc - xmlrpc-c C++ proxy class
+// Auto-generated by xml-rpc-api2cpp.
+// But for now, this file is maintained manually.  When someone figures
+// out how stuff in this directory works, maybe we'll make it an automatically
+// generated file.  -Bryan 2005.06.05.
+
+#include <string>
+
+#include "xmlrpc-c/oldcppwrapper.hpp"
+#include "SystemProxy.hpp"
+
+using namespace std;
+
+XmlRpcValue /*array*/ SystemProxy::listMethods () {
+    XmlRpcValue params = XmlRpcValue::makeArray();
+    XmlRpcValue result = this->mClient.call("system.listMethods", params);
+    return result;
+}
+
+XmlRpcValue /*array*/ SystemProxy::methodSignature (string string1) {
+    XmlRpcValue params = XmlRpcValue::makeArray();
+    params.arrayAppendItem(XmlRpcValue::makeString(string1));
+    XmlRpcValue result = this->mClient.call("system.methodSignature", params);
+    return result;
+}
+
+string SystemProxy::methodHelp (string string1) {
+    XmlRpcValue params = XmlRpcValue::makeArray();
+    params.arrayAppendItem(XmlRpcValue::makeString(string1));
+    XmlRpcValue result = this->mClient.call("system.methodHelp", params);
+    return result.getString();
+}
+
+XmlRpcValue /*array*/ SystemProxy::multicall (XmlRpcValue /*array*/ array1) {
+    XmlRpcValue params = XmlRpcValue::makeArray();
+    params.arrayAppendItem(array1);
+    XmlRpcValue result = this->mClient.call("system.multicall", params);
+    return result;
+}
diff --git a/tools/xml-rpc-api2cpp/SystemProxy.hpp b/tools/xml-rpc-api2cpp/SystemProxy.hpp
new file mode 100644 (file)
index 0000000..f7e80a2
--- /dev/null
@@ -0,0 +1,48 @@
+// SystemProxy.h - xmlrpc-c C++ proxy class
+// Auto-generated by xml-rpc-api2cpp.
+
+#ifndef _SystemProxy_H_
+#define _SystemProxy_H_ 1
+
+#include <string>
+
+#include "xmlrpc-c/oldcppwrapper.hpp"
+
+class SystemProxy {
+    XmlRpcClient mClient;
+
+public:
+    SystemProxy (const XmlRpcClient& client)
+        : mClient(client) {}
+    SystemProxy (const std::string& server_url)
+        : mClient(XmlRpcClient(server_url)) {}
+    SystemProxy (const SystemProxy& o)
+        : mClient(o.mClient) {}
+
+    SystemProxy& operator= (const SystemProxy& o) {
+        if (this != &o) mClient = o.mClient;
+        return *this;
+    }
+
+    /* Return an array of all available XML-RPC methods on this server. */
+    XmlRpcValue /*array*/ listMethods ();
+
+    /* Given the name of a method, return an array of legal
+       signatures. Each signature is an array of strings. The first item of
+       each signature is the return type, and any others items are
+       parameter types. */
+    XmlRpcValue /*array*/ methodSignature (std::string string1);
+
+    /* Given the name of a method, return a help string. */
+    std::string methodHelp (std::string string1);
+
+    /* Process an array of calls, and return an array of results. Calls
+       should be structs of the form {'methodName': string, 'params':
+       array}. Each result will either be a single-item array containg the
+       result value, or a struct of the form {'faultCode': int,
+       'faultString': string}. This is useful when you need to make lots of
+       small calls without lots of round trips. */
+    XmlRpcValue /*array*/ multicall (XmlRpcValue /*array*/ array1);
+};
+
+#endif /* _SystemProxy_H_ */
diff --git a/tools/xml-rpc-api2cpp/XmlRpcClass.cpp b/tools/xml-rpc-api2cpp/XmlRpcClass.cpp
new file mode 100644 (file)
index 0000000..2e9a1ba
--- /dev/null
@@ -0,0 +1,78 @@
+#include <iostream>
+#include <stdexcept>
+#include <vector>
+
+using namespace std;
+
+#include "xmlrpc-c/oldcppwrapper.hpp"
+
+#include "DataType.hpp"
+#include "XmlRpcFunction.hpp"
+#include "XmlRpcClass.hpp"
+
+
+//=========================================================================
+//  XmlRpcClass
+//=========================================================================
+//  This class stores information about a proxy class, and knows how to
+//  generate code.
+
+XmlRpcClass::XmlRpcClass (string class_name)
+    : mClassName(class_name)
+{
+}
+
+XmlRpcClass::XmlRpcClass (const XmlRpcClass& c)
+    : mClassName(c.mClassName),
+      mFunctions(c.mFunctions)
+{
+}
+
+XmlRpcClass& XmlRpcClass::operator= (const XmlRpcClass& c)
+{
+    if (this == &c)
+       return *this;
+    mClassName = c.mClassName;
+    mFunctions = c.mFunctions;
+    return *this;
+}
+
+void XmlRpcClass::addFunction (const XmlRpcFunction& function)
+{
+    mFunctions.push_back(function);
+}
+
+void XmlRpcClass::printDeclaration (ostream&)
+{
+    cout << "class " << mClassName << " {" << endl;
+    cout << "    XmlRpcClient mClient;" << endl;
+    cout << endl;
+    cout << "public:" << endl;
+    cout << "    " << mClassName << " (const XmlRpcClient& client)" << endl;
+    cout << "        : mClient(client) {}" << endl;
+    cout << "    " << mClassName << " (const string& server_url)" << endl;
+    cout << "        : mClient(XmlRpcClient(server_url)) {}" << endl;
+    cout << "    " << mClassName << " (const " << mClassName << "& o)" << endl;
+    cout << "        : mClient(o.mClient) {}" << endl;
+    cout << endl;
+    cout << "    " << mClassName << "& operator= (const "
+        << mClassName << "& o) {" << endl;
+    cout << "        if (this != &o) mClient = o.mClient;" << endl;
+    cout << "        return *this;" << endl;
+    cout << "    }" << endl;
+
+    vector<XmlRpcFunction>::iterator f;
+    for (f = mFunctions.begin(); f < mFunctions.end(); ++f) {
+       f->printDeclarations(cout);
+    }
+
+    cout << "};" << endl;    
+}
+
+void XmlRpcClass::printDefinition (ostream&)
+{
+    vector<XmlRpcFunction>::iterator f;
+    for (f = mFunctions.begin(); f < mFunctions.end(); ++f) {
+       f->printDefinitions(cout, mClassName);
+    }
+}
diff --git a/tools/xml-rpc-api2cpp/XmlRpcClass.hpp b/tools/xml-rpc-api2cpp/XmlRpcClass.hpp
new file mode 100644 (file)
index 0000000..4e22a7e
--- /dev/null
@@ -0,0 +1,19 @@
+#include <vector>
+
+class XmlRpcClass {
+    std::string mClassName;
+    std::vector<XmlRpcFunction> mFunctions;
+
+
+public:
+    XmlRpcClass (std::string class_name);
+    XmlRpcClass (const XmlRpcClass&);
+    XmlRpcClass& operator= (const XmlRpcClass&);
+
+    std::string className () const { return mClassName; }
+
+    void addFunction (const XmlRpcFunction& function);
+
+    void printDeclaration (ostream& out);
+    void printDefinition (ostream& out);
+};
diff --git a/tools/xml-rpc-api2cpp/XmlRpcFunction.cpp b/tools/xml-rpc-api2cpp/XmlRpcFunction.cpp
new file mode 100644 (file)
index 0000000..311fdda
--- /dev/null
@@ -0,0 +1,137 @@
+#include <iostream>
+#include <stdexcept>
+
+#include "xmlrpc-c/oldcppwrapper.hpp"
+#include "DataType.hpp"
+#include "XmlRpcFunction.hpp"
+
+using std::domain_error;
+using std::endl;
+
+
+//=========================================================================
+//  class XmlRpcFunction
+//=========================================================================
+//  Contains everything we know about a given server function, and knows
+//  how to print local bindings.
+
+XmlRpcFunction::XmlRpcFunction(const string& function_name,
+                              const string& method_name,
+                              const string& help,
+                              XmlRpcValue synopsis)
+    : mFunctionName(function_name), mMethodName(method_name),
+      mHelp(help), mSynopsis(synopsis)
+{
+}
+
+XmlRpcFunction::XmlRpcFunction (const XmlRpcFunction& f)
+    : mFunctionName(f.mFunctionName), mMethodName(f.mMethodName),
+      mHelp(f.mHelp), mSynopsis(f.mSynopsis)
+{
+}
+
+XmlRpcFunction& XmlRpcFunction::operator= (const XmlRpcFunction& f) {
+    if (this == &f)
+       return *this;
+    mFunctionName = f.mFunctionName;
+    mMethodName = f.mMethodName;
+    mHelp = f.mHelp;
+    mSynopsis = f.mSynopsis;
+    return *this;
+}
+
+void XmlRpcFunction::printDeclarations (ostream& out) {
+
+    // XXX - Do a sloppy job of printing documentation.
+    out << endl << "    /* " << mHelp << " */" << endl;
+
+    // Print each declaration.
+    size_t end = mSynopsis.arraySize();
+    for (size_t i = 0; i < end; i++)
+       printDeclaration(out, i);
+}
+
+void XmlRpcFunction::printDefinitions (ostream& out, const string& className) {
+    size_t end = mSynopsis.arraySize();
+    for (size_t i = 0; i < end; i++) {
+       out << endl;
+       printDefinition(out, className, i);
+    }
+}
+
+// Print the parameter declarations.
+void XmlRpcFunction::printParameters (ostream& out, size_t synopsis_index) {
+    size_t end = parameterCount(synopsis_index);
+    bool first = true;
+    for (size_t i = 0; i < end; i++) {
+       if (first)
+           first = false;
+       else
+           out << ", ";
+
+       const DataType& ptype (parameterType(synopsis_index, i));
+       string basename = ptype.defaultParameterBaseName(i + 1);
+       out << ptype.parameterFragment(basename);
+    }
+}
+
+void XmlRpcFunction::printDeclaration (ostream& out, size_t synopsis_index) {
+    const DataType& rtype (returnType(synopsis_index));
+    out << "    " << rtype.returnTypeFragment() << " "
+       << mFunctionName << " (";
+    printParameters(out, synopsis_index);
+    out << ");" << endl;
+}
+
+void XmlRpcFunction::printDefinition (ostream& out,
+                                     const string& className,
+                                     size_t synopsis_index)
+{
+    const DataType& rtype (returnType(synopsis_index));
+    out << rtype.returnTypeFragment() << " "
+       << className << "::" << mFunctionName << " (";
+    printParameters(out, synopsis_index);
+    out << ") {" << endl;    
+    out << "    XmlRpcValue params = XmlRpcValue::makeArray();" << endl;
+
+    /* Emit code to convert the parameters into an array of XML-RPC objects. */
+    size_t end = parameterCount(synopsis_index);
+    for (size_t i = 0; i < end; i++) {
+       const DataType& ptype (parameterType(synopsis_index, i));
+       string basename = ptype.defaultParameterBaseName(i + 1);
+       out << "    params.arrayAppendItem("
+           << ptype.inputConversionFragment(basename) << ");" << endl;
+    }
+
+    /* Emit the function call.*/
+    out << "    XmlRpcValue result = this->mClient.call(\""
+       << mMethodName << "\", params);" << endl;    
+
+    /* Emit the return statement. */
+    out << "    return " << rtype.outputConversionFragment("result")
+       << ";" << endl;
+    out << "}" << endl;
+}
+
+const DataType& XmlRpcFunction::returnType (size_t synopsis_index) {
+    XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
+    return findDataType(func_synop.arrayGetItem(0).getString());
+}
+
+size_t XmlRpcFunction::parameterCount (size_t synopsis_index) {
+    XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
+    size_t size = func_synop.arraySize();
+    if (size < 1)
+       throw domain_error("Synopsis contained no items");
+    return size - 1;
+}
+
+const DataType& XmlRpcFunction::parameterType (size_t synopsis_index,
+                                              size_t parameter_index)
+{
+    XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
+    XmlRpcValue param = func_synop.arrayGetItem(parameter_index + 1);
+    return findDataType(param.getString());
+}
+
+
diff --git a/tools/xml-rpc-api2cpp/XmlRpcFunction.hpp b/tools/xml-rpc-api2cpp/XmlRpcFunction.hpp
new file mode 100644 (file)
index 0000000..4999805
--- /dev/null
@@ -0,0 +1,37 @@
+
+#include <string>
+#include <iostream>
+
+using std::string;
+using std::ostream;
+
+class XmlRpcFunction {
+    string mFunctionName;
+    string mMethodName;
+    string mHelp;
+    XmlRpcValue mSynopsis;
+
+public: 
+    XmlRpcFunction(const string& function_name,
+                  const string& method_name,
+                  const string& help,
+                  XmlRpcValue synopsis);
+
+    XmlRpcFunction (const XmlRpcFunction&);
+    XmlRpcFunction& operator= (const XmlRpcFunction&);
+    
+    void printDeclarations (ostream& out);
+    void printDefinitions  (ostream& out, const string& className);
+
+private:
+    void printParameters  (ostream& out, size_t synopsis_index);
+    void printDeclaration (ostream& out, size_t synopsis_index);
+    void printDefinition  (ostream& out,
+                          const string& className,
+                          size_t synopsis_index);
+
+    const DataType& returnType (size_t synopsis_index);
+    size_t parameterCount (size_t synopsis_index);
+    const DataType& parameterType (size_t synopsis_index,
+                                  size_t parameter_index);
+};
diff --git a/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.1 b/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.1
new file mode 100644 (file)
index 0000000..a1c8b80
--- /dev/null
@@ -0,0 +1,62 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH XML-RPC-API2CPP 1 "June 27, 2001"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+xml-rpc-api2cpp \- Make a C++ wrapper class for an XML-RPC API
+.SH SYNOPSIS
+.B xml-rpc-api2cpp
+\fIserver-url\fR \fIremote-method-prefix\fR \fIc++-class-name\fR
+.SH DESCRIPTION
+xml-rpc-api2cpp queries an XML-RPC server using the XML-RPC
+Instrospection API designed by Edd Dumbill.  It then prints a C++
+wrapper class to standard output.  This class can be used with
+xmlrpc-c's C++ API.
+.PP
+You can find a list of supported XML-RPC server libraries (and patches
+for many others) at \fBhttp://xmlrpc-c.sourceforge.net/hacks.php\fR.
+.SH OPTIONS
+.TP
+.I server-url
+The name of the server to query.  Try
+\fBhttp://xmlrpc-c.sourceforge.net/cgi-bin/interop.cgi\fR.
+.TP
+.I remote-method-prefix
+The prefix of the methods to wrap.  For example, to wrap all the
+system.* calls, you could specify "system".
+.TP
+.I c++-class-name
+The name of the C++ class to generate.  Try "SystemProxy".
+.SH BUGS
+xml-rpc-api2cpp can't talk to certain PHP servers based on Edd
+Dumbill's PHP library, because the trailing bytes of the XML-RPC
+message get truncated in HTTP pipelining mode.  It's not clear whether
+this is a PHP, Apache or w3c-libwww bug.
+.PP
+xml-rpc-api2cpp assumes that method descriptions are ASCII text, not
+HTML as specified in the standard.  (In practice, both conventions are
+often seen.)  It may also get unhappy if method descriptions contain
+"*/".
+.PP
+In general, error messages and diagnostics are still fairly poor.
+.SH SEE ALSO
+.BR xmlrpc-c (7),
+.BR xml-rpc-api2txt (1).
+.PP
+This program is part of xmlrpc-c.
+.SH AUTHOR
+This manual page was written by Eric Kidd <eric.kidd@pobox.com>.
+It may be distributed under the same terms as the rest of xmlrpc-c.
diff --git a/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.cpp b/tools/xml-rpc-api2cpp/xml-rpc-api2cpp.cpp
new file mode 100644 (file)
index 0000000..756d50d
--- /dev/null
@@ -0,0 +1,157 @@
+#include <iostream>
+#include <stdexcept>
+
+#include "xmlrpc-c/oldcppwrapper.hpp"
+
+#include "DataType.hpp"
+#include "XmlRpcFunction.hpp"
+#include "XmlRpcClass.hpp"
+#include "SystemProxy.hpp"
+
+using namespace std;
+
+#define NAME           "xml-rpc-api2cpp"
+#define VERSION        "0.1"
+
+
+//=========================================================================
+//  function get_class_info
+//=========================================================================
+//  Connect to a remote server and extract the information we'll need to
+//  build a proxy class.
+
+XmlRpcClass get_class_info (string server_url,
+                           string class_prefix,
+                           string class_name)
+{
+    // Create a place to store our data.
+    XmlRpcClass info(class_name);
+
+    // Create a proxy class.
+    SystemProxy system(server_url);
+
+    // Fetch the full list of methods, and process the ones we want.
+    XmlRpcValue methods = system.listMethods();
+    size_t end = methods.arraySize();
+    for (size_t i = 0; i < end; i++) {
+
+       // Break the method name into two pieces.
+       string method_prefix;
+       string function_name;
+       string method_name = methods.arrayGetItem(i).getString();
+       size_t last_dot = method_name.rfind('.');
+       if (last_dot == string::npos) {
+           function_name = method_name;
+       } else {
+           method_prefix = string(method_name, 0, last_dot);
+           function_name = string(method_name, last_dot + 1);
+       }
+
+       // Decide whether we care about this function.
+       if (method_prefix == class_prefix) {
+
+           // Fetch some information about the function.
+           string help = system.methodHelp(method_name);
+           XmlRpcValue signature = system.methodSignature(method_name);
+
+           // Add this function to our class information.
+           XmlRpcFunction func(function_name, method_name, help, signature);
+           info.addFunction(func);
+       }
+    }
+
+    return info;
+}
+
+
+//=========================================================================
+//  function print_header
+//=========================================================================
+//  Print a complete header for the specified class.
+
+void print_header (ostream& out, XmlRpcClass& class_info) {
+    string class_name = class_info.className();
+    out << "// " << class_name << ".h - xmlrpc-c C++ proxy class" << endl;
+    out << "// Auto-generated by xml-rpc-api2cpp." << endl;
+    out << endl;
+
+    string header_symbol = "_" + class_name + "_H_";
+    out << "#ifndef " << header_symbol << endl;
+    out << "#define " << header_symbol << " 1" << endl;
+    out << endl;
+    out << "#include <XmlRpcCpp.h>" << endl;
+    out << endl;
+
+    class_info.printDeclaration(cout);
+
+    out << endl;
+    out << "#endif /* " << header_symbol << " */" << endl;
+}
+
+
+//=========================================================================
+//  function print_cc_file
+//=========================================================================
+//  Print a complete header for the specified class.
+
+void print_cc_file (ostream& out, XmlRpcClass& class_info) {
+    string class_name = class_info.className();
+    out << "// " << class_name << ".cc - xmlrpc-c C++ proxy class" << endl;
+    out << "// Auto-generated by xml-rpc-api2cpp." << endl;
+    out << endl;
+
+    out << "#include <XmlRpcCpp.h>" << endl;
+    out << "#include \"" << class_name << ".h\"" << endl;
+
+    class_info.printDefinition(cout);
+}
+
+
+//=========================================================================
+//  function main
+//=========================================================================
+//  For now, just a test harness.
+
+int main (int argc, char **argv) {
+
+    /* Parse our command-line arguments. */
+    if (argc != 4) {
+       cerr << argv[0] << ": Usage:" << endl
+            << "  xml-rpc-api2cpp <server_url> <method_prefix> <local_class>"
+            << endl << endl
+            << "Sample arguments:" << endl
+            << "  server_url = http://localhost/RPC2" << endl
+            << "  method_prefix = system" << endl
+            << "  local_class = SystemProxy" << endl;
+       exit(1);
+    }
+    string server_url = argv[1];
+    string method_prefix = argv[2];
+    string local_class = argv[3];
+
+    int status = 0;
+    XmlRpcClient::Initialize(NAME, VERSION);
+
+    try {
+       XmlRpcClass system = get_class_info(server_url,
+                                           method_prefix,
+                                           local_class);
+       print_header(cout, system);
+       cout << endl;
+       print_cc_file(cout, system);
+    } catch (XmlRpcFault& fault) {
+       cerr << argv[0] << ": XML-RPC fault #" << fault.getFaultCode()
+            << ": " << fault.getFaultString() << endl;
+       status = 1;
+    } catch (logic_error& err) {
+       cerr << argv[0] << ": " << err.what() << endl;
+       status = 1;
+    } catch (...) {
+       cerr << argv[0] << ": Unknown exception" << endl;
+       status = 1;
+    }
+
+    XmlRpcClient::Terminate();
+
+    return status;
+}
diff --git a/tools/xml-rpc-api2txt b/tools/xml-rpc-api2txt
new file mode 100755 (executable)
index 0000000..e771463
--- /dev/null
@@ -0,0 +1,147 @@
+#!/usr/bin/perl -w
+#
+# A handy little program to get the documentation of the available
+# methods from an XML-RPC service (via XML-RPC Introspection) and
+# print it out nicely formatted.
+#
+# (I wrote this in Perl because of all the spiffy report-generation
+# features.)
+#
+# You'll need to get Ken MacLeod's Frontier::RPC2 module from CPAN to use
+# this.
+#
+# Eric Kidd <eric.kidd@pobox.com>
+#
+# This script is part of xmlrpc-c, and may be used and distributed under
+# the same terms as the rest of the package.
+
+use strict;
+
+# One global variable for use with Perl's format routines, and one for
+# use inside an 'exec' block.
+use vars qw/$helptext $method_list/;
+
+# Try to load our Perl XML-RPC bindings, but fail gracefully.
+eval {
+    require Frontier::Client;
+};
+if ($@) {
+    print STDERR <<"EOD";
+This script requires Ken MacLeod\'s Frontier::RPC2 module. You can get this
+from CPAN or from his website at http://bitsko.slc.ut.us/~ken/xml-rpc/ .
+
+For installation instructions, see the XML-RPC HOWTO at:
+    http://www.linuxdoc.org/HOWTO/XML-RPC-HOWTO/index.html
+
+EOD
+    exit 1;
+}
+
+# Parse our command-line arguments.
+if (@ARGV != 1 || $ARGV[0] eq "--help") {
+    print STDERR "Usage: xml-rpc-api2txt serverURL\n";
+    exit 1;
+}
+
+my $server = Frontier::Client->new(url => $ARGV[0]);
+
+# Try (very carefully) to get our a list of methods from the server.
+local $method_list;
+eval {
+    $method_list = $server->call('system.listMethods');
+};
+if ($@) {
+    print STDERR <<"EOD";
+An error occurred while trying to talk to the XML-RPC server:
+
+  $@
+
+This may have been caused by several things--the server might not support
+introspection, it might not be an XML-RPC server, or your network might be
+down. Try the following:
+
+  xml-rpc-api2txt http://xmlrpc-c.sourceforge.net/api/sample.php
+
+EOD
+    exit 1;
+}
+
+# Enter the methods into a hashtable.
+my @methods = sort @$method_list;
+my %method_table;
+foreach my $method (@methods) {
+    $method_table{$method} = {};
+}
+
+# Get more information for the hash table. Since we need to make lots and
+# lots of very small XML-RPC calls, we'd like to use system.multicall to
+# reduce the latency.
+if (defined $method_table{'system.multicall'}) {
+
+    # This is messy but fast. Everybody hates HTTP round-trip lag, right?
+    my @call;
+    foreach my $method (@methods) {
+       push @call, {methodName => 'system.methodSignature',
+                    params => [$method]};
+       push @call, {methodName => 'system.methodHelp',
+                    params => [$method]};
+    }
+    my @result = @{$server->call('system.multicall', \@call)};
+    for (my $i = 0; $i < @methods; $i++) {
+       my $method = $methods[$i];
+       $method_table{$method}->{'signatures'} = $result[2*$i]->[0];
+       $method_table{$method}->{'help'} = $result[2*$i+1]->[0];
+    }
+} else {
+
+    # This is easy but slow (especially over backbone links).
+    foreach my $method (@methods) {
+       my $signature = $server->call('system.methodSignature', $method);
+       my $help = $server->call('system.methodHelp', $method);
+       $method_table{$method}->{'signatures'} = $signature;
+       $method_table{$method}->{'help'} = $help;
+    }
+}
+
+# Now, we need to dump the API.
+print <<"EOD";
+XML-RPC API for $ARGV[0]
+
+See http://www.linuxdoc.org/HOWTO/XML-RPC-HOWTO/index.html for instructions
+on using XML-RPC with Perl, Python, Java, C, C++, PHP, etc.
+EOD
+foreach my $method (@methods) {
+    print "\n";
+
+    # Print a synopsis of the function.
+    if ($method_table{$method}->{'signatures'} eq 'undef') {
+       # No documentation. Bad server. No biscuit.
+       print "unknown $method (...)\n";
+    } else {
+       for my $signature (@{$method_table{$method}->{'signatures'}}) {
+           my $return_type = shift @$signature;
+           my $arguments = join(", ", @$signature);
+           print "$return_type $method ($arguments)\n";
+       }
+    }
+    print "\n";
+
+    my $help = $method_table{$method}->{'help'};
+    if ($help =~ /\n/) {
+       # Text has already been broken into lines by the server, so just
+       # indent it by two spaces and hope for the best.
+       my @lines = split(/\n/, $help);
+       my $help = "  " . join("\n  ", @lines);
+       print "$help\n";
+    } else {
+       # Print our help text in a nicely-wrapped fashion using Perl's
+       # formatting routines.
+       $helptext = $method_table{$method}->{'help'};
+       write;
+    }
+}
+
+format STDOUT =
+  ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
+  $helptext
+.
diff --git a/tools/xml-rpc-api2txt.1 b/tools/xml-rpc-api2txt.1
new file mode 100644 (file)
index 0000000..a9e1ee3
--- /dev/null
@@ -0,0 +1,47 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH XML-RPC-API2TXT 1 "June 27, 2001"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+xml-rpc-api2txt \- Print out a description of an XML-RPC API as text
+.SH SYNOPSIS
+.B xml-rpc-api2txt
+\fIserver-url\fR
+.SH DESCRIPTION
+xml-rpc-api2txt queries an XML-RPC server using the XML-RPC
+Instrospection API designed by Edd Dumbill.  It then prints the
+results to standard output in a nicely formatted form, suitable for
+sending via e-mail.
+.PP
+You can find a list of supported XML-RPC server libraries (and patches
+for many others) at \fBhttp://xmlrpc-c.sourceforge.net/hacks.php\fR.
+.SH OPTIONS
+.TP
+.I server-url
+The name of the server to query.  Try
+\fBhttp://xmlrpc-c.sourceforge.net/cgi-bin/interop.cgi\fR.
+.SH BUGS
+xml-rpc-api2txt assumes that method descriptions are ASCII text, not
+HTML as specified in the standard.  (In practice, both conventions are
+often seen.)
+.SH SEE ALSO
+.BR xmlrpc-c (7),
+.BR xml-rpc-api2cpp (1).
+.PP
+This program is part of xmlrpc-c.
+.SH AUTHOR
+This manual page was written by Eric Kidd <eric.kidd@pobox.com>.
+It may be distributed under the same terms as the rest of xmlrpc-c.
diff --git a/tools/xmlrpc/.cvsignore b/tools/xmlrpc/.cvsignore
new file mode 100644 (file)
index 0000000..73a3b1b
--- /dev/null
@@ -0,0 +1 @@
+xmlrpc
diff --git a/tools/xmlrpc/Makefile b/tools/xmlrpc/Makefile
new file mode 100644 (file)
index 0000000..fcc95ea
--- /dev/null
@@ -0,0 +1,66 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+# BLDDIR is for use in places where a symbolic link won't work.
+# BUILDDIR is for places in Makefile.common that can use the 'blddir'
+# symbolic link (but in other directories, doesn't).
+BLDDIR = $(SRCDIR)
+BUILDDIR = blddir
+
+default: all
+
+include $(BLDDIR)/Makefile.config
+
+PROGRAMS_TO_INSTALL = xmlrpc
+
+include ../Makefile.common
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include
+
+CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD)
+
+LDFLAGS = $(LADD)
+
+all: xmlrpc
+
+UTIL_OBJS = cmdline_parser.o getoptx.o casprintf.o
+UTILS = $(UTIL_OBJS:%=$(UTIL_DIR)/%)
+
+# These are the Libtool .la files.  We use them only for make dependencies.
+# We'd like to use these in the link rule, by using libtool --link, but
+# Libtool adds -l options to the link to cover the dependencies that are
+# recorded inside the shared libraries.  And it doesn't add the necessary
+# -L options (it can't), so we end up with a messy mixture of the two
+# forms of specifying libraries.
+
+LIBS = $(LIBXMLRPC_CLIENT) $(LIBXMLRPC) $(LIBXMLRPC_XML) $(LIBXMLRPC_UTIL)
+
+XMLRPC_OBJS = xmlrpc.o dumpvalue.o
+
+xmlrpc: $(XMLRPC_OBJS) $(LIBS) $(UTILS)
+       $(CCLD) -o $@ $(LDFLAGS) $(XMLRPC_OBJS) $(UTILS) $(CLIENT_LDLIBS)
+
+%.o:%.c
+       $(CC) -c $(CFLAGS) $<
+
+*.c: config.h
+
+config.h:
+       $(LN_S) $(BLDDIR)/xmlrpc_config.h $@
+
+# This Makefile.config dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(BLDDIR)/Makefile.config: blddir srcdir
+
+include Makefile.depend
+
+.PHONY: dep
+dep: dep-common
+
+.PHONY: clean
+clean: clean-common
+       rm -f xmlrpc config.h
+
+.PHONY: distclean
+distclean: clean distclean-common
diff --git a/tools/xmlrpc/Makefile.depend b/tools/xmlrpc/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/xmlrpc/dumpvalue.c b/tools/xmlrpc/dumpvalue.c
new file mode 100644 (file)
index 0000000..4547380
--- /dev/null
@@ -0,0 +1,367 @@
+/* dumpvalue() service, which prints to Standard Output the value of
+   an xmlrpc_value.
+
+   We've put this in a separate module in hopes that it eventually can be
+   used for debugging purposes in other places.
+*/
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"  /* information about this build environment */
+#include "casprintf.h"
+#include "mallocvar.h"
+
+#include "xmlrpc-c/base.h"
+
+#include "dumpvalue.h"
+
+
+
+static void
+dumpInt(const char *   const prefix,
+        xmlrpc_value * const valueP) {
+
+    xmlrpc_env env;
+    xmlrpc_int value;
+    
+    xmlrpc_env_init(&env);
+
+    xmlrpc_parse_value(&env, valueP, "i", &value);
+    
+    if (env.fault_occurred)
+        printf("Unable to parse integer xmlrpc_value %lx.  %s\n",
+               (unsigned long)valueP, env.fault_string);
+    else
+        printf("%sInteger: %d\n", prefix, value);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpBool(const char *   const prefix,
+         xmlrpc_value * const valueP) {
+
+    xmlrpc_env env;
+    xmlrpc_bool value;
+    
+    xmlrpc_env_init(&env);
+
+    xmlrpc_parse_value(&env, valueP, "b", &value);
+    
+    if (env.fault_occurred)
+        printf("Unable to parse boolean xmlrpc_value %lx.  %s\n",
+               (unsigned long)valueP, env.fault_string);
+    else
+        printf("%sBoolean: %s\n", prefix, value ? "TRUE" : "FALSE");
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+
+static void
+dumpDouble(const char *   const prefix,
+           xmlrpc_value * const valueP) {
+
+    xmlrpc_env env;
+    xmlrpc_double value;
+    
+    xmlrpc_env_init(&env);
+
+    xmlrpc_parse_value(&env, valueP, "d", &value);
+    
+    if (env.fault_occurred)
+        printf("Unable to parse floating point number xmlrpc_value %lx.  %s\n",
+               (unsigned long)valueP, env.fault_string);
+    else
+        printf("%sFloating Point: %f\n", prefix, value);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpDatetime(const char *   const prefix,
+             xmlrpc_value * const valueP) {
+
+    printf("%sDon't know how to print datetime value %lx.\n", 
+           prefix, (unsigned long) valueP);
+}
+
+
+
+static void
+dumpString(const char *   const prefix,
+           xmlrpc_value * const valueP) {
+
+    xmlrpc_env env;
+    const char * value;
+    
+    xmlrpc_env_init(&env);
+
+    xmlrpc_parse_value(&env, valueP, "s", &value);
+    
+    if (env.fault_occurred)
+        printf("Unable to parse string xmlrpc_value %lx.  %s\n",
+               (unsigned long)valueP, env.fault_string);
+    else
+        printf("%sString: '%s'\n", prefix, value);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpBase64(const char *   const prefix,
+           xmlrpc_value * const valueP) {
+
+    xmlrpc_env env;
+    const unsigned char * value;
+    size_t length;
+    
+    xmlrpc_env_init(&env);
+
+    xmlrpc_parse_value(&env, valueP, "6", &value, &length);
+    
+    if (env.fault_occurred)
+        printf("Unable to parse base64 bit string xmlrpc_value %lx.  %s\n",
+               (unsigned long)valueP, env.fault_string);
+    else {
+        unsigned int i;
+
+        printf("%sBit string: ", prefix);
+        for (i = 0; i < length; ++i)
+            printf("%02x", value[i]);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpArray(const char *   const prefix,
+          xmlrpc_value * const arrayP) {
+
+    xmlrpc_env env;
+    unsigned int arraySize;
+
+    xmlrpc_env_init(&env);
+
+    XMLRPC_ASSERT_ARRAY_OK(arrayP);
+
+    arraySize = xmlrpc_array_size(&env, arrayP);
+    if (env.fault_occurred)
+        printf("Unable to get array size.  %s\n", env.fault_string);
+    else {
+        int const spaceCount = strlen(prefix);
+
+        unsigned int i;
+        const char * blankPrefix;
+
+        printf("%sArray of %u items:\n", prefix, arraySize);
+
+        casprintf(&blankPrefix, "%*s", spaceCount, "");
+
+        for (i = 0; i < arraySize; ++i) {
+            xmlrpc_value * valueP;
+
+            xmlrpc_array_read_item(&env, arrayP, i, &valueP);
+
+            if (env.fault_occurred)
+                printf("Unable to get array item %u\n", i);
+            else {
+                const char * prefix2;
+
+                casprintf(&prefix2, "%s  Index %2u ", blankPrefix, i);
+                dumpValue(prefix2, valueP);
+                strfree(prefix2);
+
+                xmlrpc_DECREF(valueP);
+            }
+        }
+        strfree(blankPrefix);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpStructMember(const char *   const prefix,
+                 xmlrpc_value * const structP,
+                 unsigned int   const index) {
+
+    xmlrpc_env env;
+
+    xmlrpc_value * keyP;
+    xmlrpc_value * valueP;
+    
+    xmlrpc_env_init(&env);
+
+    xmlrpc_struct_read_member(&env, structP, index, &keyP, &valueP);
+
+    if (env.fault_occurred)
+        printf("Unable to get struct member %u\n", index);
+    else {
+        int const blankCount = strlen(prefix);
+        const char * prefix2;
+        const char * blankPrefix;
+
+        casprintf(&prefix2, "%s  Key:   ", prefix);
+        dumpValue(prefix2, keyP);
+        strfree(prefix2);
+
+        casprintf(&blankPrefix, "%*s", blankCount, "");
+        
+        casprintf(&prefix2, "%s  Value: ", blankPrefix);
+        dumpValue(prefix2, valueP);
+        strfree(prefix2);
+
+        strfree(blankPrefix);
+
+        xmlrpc_DECREF(keyP);
+        xmlrpc_DECREF(valueP);
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpStruct(const char *   const prefix,
+           xmlrpc_value * const structP) {
+
+    xmlrpc_env env;
+    unsigned int structSize;
+
+    xmlrpc_env_init(&env);
+
+    structSize = xmlrpc_struct_size(&env, structP);
+    if (env.fault_occurred)
+        printf("Unable to get struct size.  %s\n", env.fault_string);
+    else {
+        unsigned int i;
+
+        printf("%sStruct of %u members:\n", prefix, structSize);
+
+        for (i = 0; i < structSize; ++i) {
+            const char * prefix1;
+
+            if (i == 0)
+                prefix1 = strdup(prefix);
+            else {
+                int const blankCount = strlen(prefix);
+                casprintf(&prefix1, "%*s", blankCount, "");
+            }            
+            dumpStructMember(prefix1, structP, i);
+
+            strfree(prefix1);
+        }
+    }
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpCPtr(const char *   const prefix,
+         xmlrpc_value * const valueP) {
+
+    xmlrpc_env env;
+    const char * value;
+
+    xmlrpc_env_init(&env);
+
+    xmlrpc_parse_value(&env, valueP, "p", &value);
+        
+    if (env.fault_occurred)
+        printf("Unable to parse C pointer xmlrpc_value %lx.  %s\n",
+               (unsigned long)valueP, env.fault_string);
+    else
+        printf("%sC pointer: '%p'\n", prefix, value);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpNil(const char *   const prefix,
+        xmlrpc_value * const valueP) {
+
+    xmlrpc_env env;
+
+    xmlrpc_env_init(&env);
+
+    xmlrpc_parse_value(&env, valueP, "n");
+        
+    if (env.fault_occurred)
+        printf("Unable to parse nil value xmlrpc_value %lx.  %s\n",
+               (unsigned long)valueP, env.fault_string);
+    else
+        printf("%sNil\n", prefix);
+
+    xmlrpc_env_clean(&env);
+}
+
+
+
+static void
+dumpUnknown(const char *   const prefix,
+            xmlrpc_value * const valueP) {
+
+    printf("%sDon't recognize value type %u of xmlrpc_value %lx.\n", 
+           prefix, xmlrpc_value_type(valueP), (unsigned long)valueP);
+    printf("%sCan't print it.\n", prefix);
+}
+
+
+
+void
+dumpValue(const char *   const prefix,
+          xmlrpc_value * const valueP) {
+
+    switch (xmlrpc_value_type(valueP)) {
+    case XMLRPC_TYPE_INT:
+        dumpInt(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_BOOL: 
+        dumpBool(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_DOUBLE: 
+        dumpDouble(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_DATETIME:
+        dumpDatetime(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_STRING: 
+        dumpString(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_BASE64:
+        dumpBase64(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_ARRAY: 
+        dumpArray(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_STRUCT:
+        dumpStruct(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_C_PTR:
+        dumpCPtr(prefix, valueP);
+        break;
+    case XMLRPC_TYPE_NIL:
+        dumpNil(prefix, valueP);
+        break;
+    default:
+        dumpUnknown(prefix, valueP);
+    }
+}
diff --git a/tools/xmlrpc/dumpvalue.h b/tools/xmlrpc/dumpvalue.h
new file mode 100644 (file)
index 0000000..84be009
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef DUMPVALUE_H_INCLUDED
+#define DUMPVALUE_H_INCLUDED
+
+struct _xmlrpc_value;
+
+void
+dumpValue(const char *           const prefix,
+          struct _xmlrpc_value * const valueP);
+
+#endif
diff --git a/tools/xmlrpc/xmlrpc.c b/tools/xmlrpc/xmlrpc.c
new file mode 100644 (file)
index 0000000..f3c8d3c
--- /dev/null
@@ -0,0 +1,514 @@
+/* Make an XML-RPC call.
+
+   User specifies details of the call on the command line.
+
+   We print the result on Standard Output.
+
+   Example:
+
+     $ xmlrpc http://localhost:8080/RPC2 sample.add i/3 i/5
+     Result:
+       Integer: 8
+
+     $ xmlrpc localhost:8080 sample.add i/3 i/5
+     Result:
+       Integer: 8
+
+   This is just the beginnings of this program.  It should be extended
+   to deal with all types of parameters and results.
+
+   An example of a good syntax for parameters would be:
+
+     $ xmlrpc http://www.oreillynet.com/meerkat/xml-rpc/server.php \
+         meerkat.getItems \
+         struct/{search:linux,descriptions:i/76,time_period:12hour}
+     Result:
+       Array:
+         Struct:
+           title: String: DatabaseJournal: OpenEdge-Based Finance ...
+           link: String: http://linuxtoday.com/news_story.php3?ltsn=...
+           description: String: "Finance application with embedded ...
+         Struct:
+           title: ...
+           link: ...
+           description: ...
+
+*/
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"  /* information about this build environment */
+#include "casprintf.h"
+#include "mallocvar.h"
+#include "cmdline_parser.h"
+#include "dumpvalue.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+
+#define NAME "xmlrpc command line program"
+#define VERSION "1.0"
+
+struct cmdlineInfo {
+    const char *  url;
+    const char *  username;
+    const char *  password;
+    const char *  methodName;
+    unsigned int  paramCount;
+    const char ** params;
+        /* Array of parameters, in order.  Has 'paramCount' entries. */
+    const char *  transport;
+        /* Name of XML transport he wants to use.  NULL if he has no 
+           preference.
+        */
+    const char *  curlinterface;
+        /* "network interface" parameter for the Curl transport.  (Not
+           valid if 'transport' names a non-Curl transport).
+        */
+    xmlrpc_bool   curlnoverifypeer;
+    xmlrpc_bool   curlnoverifyhost;
+    const char *  curluseragent;
+};
+
+
+
+static void 
+die_if_fault_occurred (xmlrpc_env * const envP) {
+    if (envP->fault_occurred) {
+        fprintf(stderr, "Error: %s (%d)\n",
+                envP->fault_string, envP->fault_code);
+        exit(1);
+    }
+}
+
+
+
+static void GNU_PRINTF_ATTR(2,3)
+setError(xmlrpc_env * const envP, const char format[], ...) {
+    va_list args;
+    const char * faultString;
+
+    va_start(args, format);
+
+    cvasprintf(&faultString, format, args);
+    va_end(args);
+
+    xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, faultString);
+
+    strfree(faultString);
+}
+      
+
+
+static void
+processArguments(xmlrpc_env *         const envP,
+                 cmdlineParser        const cp,
+                 struct cmdlineInfo * const cmdlineP) {
+
+    if (cmd_argumentCount(cp) < 2)
+        setError(envP, "Not enough arguments.  Need at least a URL and "
+                 "method name.");
+    else {
+        unsigned int i;
+        
+        cmdlineP->url        = cmd_getArgument(cp, 0);
+        cmdlineP->methodName = cmd_getArgument(cp, 1);
+        cmdlineP->paramCount = cmd_argumentCount(cp) - 2;
+        MALLOCARRAY(cmdlineP->params, cmdlineP->paramCount);
+        for (i = 0; i < cmdlineP->paramCount; ++i)
+            cmdlineP->params[i] = cmd_getArgument(cp, i+2);
+    }
+}
+
+
+
+static void
+chooseTransport(xmlrpc_env *  const envP ATTR_UNUSED,
+                cmdlineParser const cp,
+                const char ** const transportPP) {
+    
+    const char * transportOpt = cmd_getOptionValueString(cp, "transport");
+
+    if (transportOpt) {
+        *transportPP = transportOpt;
+    } else {
+        if (cmd_optionIsPresent(cp, "curlinterface") || 
+            cmd_optionIsPresent(cp, "curlnoverifypeer") ||
+            cmd_optionIsPresent(cp, "curlnoverifyhost") ||
+            cmd_optionIsPresent(cp, "curluseragent"))
+
+            *transportPP = strdup("curl");
+        else
+            *transportPP = NULL;
+    }
+}
+
+
+
+static void
+parseCommandLine(xmlrpc_env *         const envP,
+                 int                  const argc,
+                 const char **        const argv,
+                 struct cmdlineInfo * const cmdlineP) {
+
+    cmdlineParser const cp = cmd_createOptionParser();
+
+    const char * error;
+
+    cmd_defineOption(cp, "transport",        OPTTYPE_STRING);
+    cmd_defineOption(cp, "username",         OPTTYPE_STRING);
+    cmd_defineOption(cp, "password",         OPTTYPE_STRING);
+    cmd_defineOption(cp, "curlinterface",    OPTTYPE_STRING);
+    cmd_defineOption(cp, "curlnoverifypeer", OPTTYPE_STRING);
+    cmd_defineOption(cp, "curlnoverifyhost", OPTTYPE_STRING);
+    cmd_defineOption(cp, "curluseragent",    OPTTYPE_STRING);
+
+    cmd_processOptions(cp, argc, argv, &error);
+
+    if (error) {
+        setError(envP, "Command syntax error.  %s", error);
+        strfree(error);
+    } else {
+        cmdlineP->username  = cmd_getOptionValueString(cp, "username");
+        cmdlineP->password  = cmd_getOptionValueString(cp, "password");
+
+        if (cmdlineP->username && !cmdlineP->password)
+            setError(envP, "When you specify -username, you must also "
+                     "specify -password.");
+        else {
+            chooseTransport(envP, cp, &cmdlineP->transport);
+
+            cmdlineP->curlinterface = 
+                cmd_getOptionValueString(cp, "curlinterface");
+            cmdlineP->curlnoverifypeer =
+                cmd_optionIsPresent(cp, "curlnoverifypeer");
+            cmdlineP->curlnoverifyhost =
+                cmd_optionIsPresent(cp, "curlnoverifyhost");
+            cmdlineP->curluseragent =
+                cmd_getOptionValueString(cp, "curluseragent");
+
+            if ((!cmdlineP->transport || 
+                 strcmp(cmdlineP->transport, "curl") != 0)
+                &&
+                (cmdlineP->curlinterface ||
+                 cmdlineP->curlnoverifypeer ||
+                 cmdlineP->curlnoverifyhost ||
+                 cmdlineP->curluseragent))
+                setError(envP, "You may not specify a Curl transport "
+                         "option unless you also specify -transport=curl");
+
+            processArguments(envP, cp, cmdlineP);
+        }
+    }
+    cmd_destroyOptionParser(cp);
+}
+
+
+
+static void
+freeCmdline(struct cmdlineInfo const cmdline) {
+
+    unsigned int i;
+    
+    strfree(cmdline.url);
+    strfree(cmdline.methodName);
+    if (cmdline.transport)
+        strfree(cmdline.transport);
+    if (cmdline.curlinterface)
+        strfree(cmdline.curlinterface);
+    if (cmdline.curluseragent)
+        strfree(cmdline.curluseragent);
+    if (cmdline.username)
+        strfree(cmdline.username);
+    if (cmdline.password)
+        strfree(cmdline.password);
+    for (i = 0; i < cmdline.paramCount; ++i)
+        strfree(cmdline.params[i]);
+}
+
+
+
+static void
+computeUrl(const char *  const urlArg,
+           const char ** const urlP) {
+
+    if (strstr(urlArg, "://") != 0)
+        casprintf(urlP, "%s", urlArg);
+    else
+        casprintf(urlP, "http://%s/RPC2", urlArg);
+}
+
+
+
+static void
+buildString(xmlrpc_env *    const envP,
+            const char *    const valueString,
+            xmlrpc_value ** const paramPP) {
+
+    *paramPP = xmlrpc_build_value(envP, "s", valueString);
+}
+
+
+
+static void
+buildInt(xmlrpc_env *    const envP,
+         const char *    const valueString,
+         xmlrpc_value ** const paramPP) {
+
+    if (strlen(valueString) < 1)
+        setError(envP, "Integer argument has nothing after the 'i/'");
+    else {
+        long value;
+        char * tailptr;
+        
+        value = strtol(valueString, &tailptr, 10);
+
+        if (*tailptr != '\0')
+            setError(envP, 
+                     "Integer argument has non-digit crap in it: '%s'",
+                     tailptr);
+        else
+            *paramPP = xmlrpc_build_value(envP, "i", value);
+    }
+}
+
+
+
+static void
+buildDouble(xmlrpc_env *    const envP,
+            const char *    const valueString,
+            xmlrpc_value ** const paramPP) {
+
+    if (strlen(valueString) < 1)
+        setError(envP, "\"Double\" argument has nothing after the 'd/'");
+    else {
+        double value;
+        char * tailptr;
+
+        value = strtod(valueString, &tailptr);
+
+        if (*tailptr != '\0')
+            setError(envP, 
+                     "\"Double\" argument has non-decimal crap in it: '%s'",
+                     tailptr);
+        else
+            *paramPP = xmlrpc_build_value(envP, "d", value);
+    }
+}
+
+
+
+static void
+buildBool(xmlrpc_env *    const envP,
+          const char *    const valueString,
+          xmlrpc_value ** const paramPP) {
+
+    if (strcmp(valueString, "t") == 0 ||
+        strcmp(valueString, "true") == 0)
+        *paramPP = xmlrpc_build_value(envP, "b", 1);
+    else if (strcmp(valueString, "f") == 0 ||
+        strcmp(valueString, "false") == 0)
+        *paramPP = xmlrpc_build_value(envP, "b", 0);
+    else
+        setError(envP, "Boolean argument has unrecognized value '%s'.  "
+                 "recognized values are 't', 'f', 'true', and 'false'.",
+                 valueString);
+} 
+
+
+
+static void
+buildNil(xmlrpc_env *    const envP,
+         const char *    const valueString,
+         xmlrpc_value ** const paramPP) {
+
+    if (strlen(valueString) > 0)
+        setError(envP, "Nil argument has something after the 'n/'");
+    else {
+        *paramPP = xmlrpc_build_value(envP, "n");
+    }
+}
+
+
+
+static void
+computeParameter(xmlrpc_env *    const envP,
+                 const char *    const paramArg,
+                 xmlrpc_value ** const paramPP) {
+
+    if (strncmp(paramArg, "s/", 2) == 0)
+        buildString(envP, &paramArg[2], paramPP);
+    else if (strncmp(paramArg, "i/", 2) == 0) 
+        buildInt(envP, &paramArg[2], paramPP);
+    else if (strncmp(paramArg, "d/", 2) == 0) 
+        buildDouble(envP, &paramArg[2], paramPP);
+    else if (strncmp(paramArg, "b/", 2) == 0)
+        buildBool(envP, &paramArg[2], paramPP);
+    else if (strncmp(paramArg, "n/", 2) == 0)
+        buildNil(envP, &paramArg[2], paramPP);
+    else {
+        /* It's not in normal type/value format, so we take it to be
+           the shortcut string notation 
+        */
+        buildString(envP, paramArg, paramPP);
+    }
+}
+
+
+
+static void
+computeParamArray(xmlrpc_env *    const envP,
+                  unsigned int    const paramCount,
+                  const char **   const params,
+                  xmlrpc_value ** const paramArrayPP) {
+    
+    unsigned int i;
+
+    xmlrpc_value * paramArrayP;
+
+    paramArrayP = xmlrpc_build_value(envP, "()");
+
+    for (i = 0; i < paramCount && !envP->fault_occurred; ++i) {
+        xmlrpc_value * paramP;
+
+        computeParameter(envP, params[i], &paramP);
+
+        if (!envP->fault_occurred) {
+            xmlrpc_array_append_item(envP, paramArrayP, paramP);
+
+            xmlrpc_DECREF(paramP);
+        }
+    }
+    *paramArrayPP = paramArrayP;
+}
+
+
+
+static void
+dumpResult(xmlrpc_value * const resultP) {
+
+    printf("Result:\n\n");
+
+    dumpValue("", resultP);
+}
+
+
+
+static void
+doCall(xmlrpc_env *               const envP,
+       const char *               const transport,
+       const char *               const curlinterface,
+       xmlrpc_bool                const curlnoverifypeer,
+       xmlrpc_bool                const curlnoverifyhost,
+       const char *               const curluseragent,
+       const xmlrpc_server_info * const serverInfoP,
+       const char *               const methodName,
+       xmlrpc_value *             const paramArrayP,
+       xmlrpc_value **            const resultPP) {
+    
+    struct xmlrpc_clientparms clientparms;
+
+    XMLRPC_ASSERT(xmlrpc_value_type(paramArrayP) == XMLRPC_TYPE_ARRAY);
+
+    clientparms.transport = transport;
+
+    if (transport && strcmp(transport, "curl") == 0) {
+        struct xmlrpc_curl_xportparms * curlXportParmsP;
+        MALLOCVAR(curlXportParmsP);
+
+        curlXportParmsP->network_interface = curlinterface;
+        curlXportParmsP->no_ssl_verifypeer = curlnoverifypeer;
+        curlXportParmsP->no_ssl_verifyhost = curlnoverifyhost;
+        curlXportParmsP->user_agent        = curluseragent;
+        
+        clientparms.transportparmsP = (struct xmlrpc_xportparms *) 
+            curlXportParmsP;
+        clientparms.transportparm_size = XMLRPC_CXPSIZE(user_agent);
+    } else {
+        clientparms.transportparmsP = NULL;
+        clientparms.transportparm_size = 0;
+    }
+    xmlrpc_client_init2(envP, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, 
+                        &clientparms, XMLRPC_CPSIZE(transportparm_size));
+    if (!envP->fault_occurred) {
+        *resultPP = xmlrpc_client_call_server_params(
+            envP, serverInfoP, methodName, paramArrayP);
+    
+        xmlrpc_client_cleanup();
+    }
+    if (clientparms.transportparmsP)
+        free(clientparms.transportparmsP);
+}
+
+
+
+static void
+createServerInfo(xmlrpc_env *          const envP,
+                 const char *          const serverUrl,
+                 const char *          const userName,
+                 const char *          const password,
+                 xmlrpc_server_info ** const serverInfoPP) {
+
+    xmlrpc_server_info * serverInfoP;
+
+    serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+    if (!envP->fault_occurred) {
+        if (userName) {
+            xmlrpc_server_info_set_basic_auth(
+                envP, serverInfoP, userName, password);
+        }
+    }
+    *serverInfoPP = serverInfoP;
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv) {
+
+    struct cmdlineInfo cmdline;
+    xmlrpc_env env;
+    xmlrpc_value * paramArrayP;
+    xmlrpc_value * resultP;
+    const char * url;
+    xmlrpc_server_info * serverInfoP;
+
+    xmlrpc_env_init(&env);
+
+    parseCommandLine(&env, argc, argv, &cmdline);
+    die_if_fault_occurred(&env);
+
+    computeUrl(cmdline.url, &url);
+
+    computeParamArray(&env, cmdline.paramCount, cmdline.params, &paramArrayP);
+    die_if_fault_occurred(&env);
+
+    createServerInfo(&env, url, cmdline.username, cmdline.password,
+                     &serverInfoP);
+    die_if_fault_occurred(&env);
+
+    doCall(&env, cmdline.transport, cmdline.curlinterface,
+           cmdline.curlnoverifypeer, cmdline.curlnoverifyhost,
+           cmdline.curluseragent,
+           serverInfoP,
+           cmdline.methodName, paramArrayP, 
+           &resultP);
+    die_if_fault_occurred(&env);
+
+    dumpResult(resultP);
+    
+    strfree(url);
+
+    xmlrpc_DECREF(resultP);
+
+    freeCmdline(cmdline);
+
+    xmlrpc_env_clean(&env);
+    
+    return 0;
+}
diff --git a/tools/xmlrpc/xmlrpc.html b/tools/xmlrpc/xmlrpc.html
new file mode 100644 (file)
index 0000000..3d41c19
--- /dev/null
@@ -0,0 +1,249 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<title>Xmlrpc User Manual</title>
+<body>
+
+<p><b>xmlrpc</b> makes an XML-RPC remote procedure call (RPC) and displays
+the response.  <b>xmlrpc</b> runs an XML-RPC client.
+
+<p>This program is mainly useful for debugging and learning about
+XML-RPC servers.  XML-RPC is such that the RPCs normally need to be made
+by a program rather than a person to be of use.
+
+<p>A similar tool done as a web form is at <a
+href="http://gggeek.damacom.it/debugger/">
+http://gggeek.damacom.it/debugger/</a>
+
+<h2>Examples</h2>
+
+<pre>
+<tt>
+     $ xmlrpc http://localhost:8080/RPC2 sample.add i/3 i/5
+       Result:
+         Integer: 8
+</tt>
+</pre>
+
+<pre>
+<tt>
+     $ xmlrpc localhost:8080 sample.add i/3 i/5
+       Result:
+         Integer: 8
+     
+</tt>
+</pre>
+
+<pre>
+<tt>
+     $ xmlrpc http://xmlrpc.server.net/~bryanh echostring \
+         &quot;s/This is a string&quot;
+     Result:
+       String: This is a string
+
+</tt>
+</pre>
+
+<pre>
+<tt>
+     $ xmlrpc http://xmlrpc.server.net/~bryanh echostring \
+         &quot;This is a string in shortcut syntax&quot;
+     Result:
+       String: This is a string in shortcut syntax
+
+</tt>
+</pre>
+<pre>
+<tt>
+     $ xmlrpc http://xmlrpc.server.net sample.add i/3 i/5 \
+         transport=curl -curlinterface=eth1 -username=bryanh -password=passw0rd
+       Result:
+         Integer: 8
+     
+</tt>
+</pre>
+
+<h2>Overview</h2>
+<p>
+<b>xmlrpc</b>
+<i>url</i>
+<i>methodName</i>
+<i>parameter</i> ...
+[<b>-transport=</b><i>transportname</i>]
+[<b>-username=</b><i>username</i> <b>-password=</b><i>password</i>]
+[<b>-curlinterface</b>={<i>interface</i>|<i>host</i>}]
+[<b>-curlnoverifypeer</b>]
+[<b>-curlnoverifyhost</b>]
+
+<p><i>parameter</i>:
+
+<p>
+<b>i/</b><i>integer</i> |
+<b>s/</b><i>string</i> |
+<b>b/</b>{<b>true</b>|<b>false</b>|<b>t</b>|<b>f</b>} |
+<b>d/</b><i>realnum</i> |
+<b>n/</b> |
+<b><i>string</i></b>
+
+
+<P>Minimum unique abbreviation of option is acceptable.  You may use double
+hyphens instead of single hyphen to denote options.  You may use white
+space in place of the equals sign to separate an option name from its value.
+
+
+<h2>Arguments</h2>
+
+<dl>
+<dt><i>url</i>
+
+<dd>This is the URL of the XML-RPC server.  As XML-RPC uses HTTP, this
+must be an HTTP url.  However, if you don't specify a type (&quot;http:&quot;)
+in the URL, <b>xmlrpc</b> assumes an &quot;http://&quot; prefix and a
+&quot;/RPC2&quot; suffix.  <b>RPC2</b> is the conventional file name for
+an XML-RPC responder.
+
+<dt><i>methodName</i>
+
+<dd>The name of the XML-RPC method you want to invoke.
+
+<dt><i>parameter</i> ...
+
+<dd>The list of parameters for the RPC.  <b>xmlrpc</b> turns each of these
+arguments into an XML-RPC parameter, in the order given.  You may specify
+no parameters if you like.
+
+<p>You specify the data type of the parameter with a prefix ending in
+a slash.  Example: <b>i/5</b>.  Here, the &quot;i&quot; signifies an
+integer data type.  &quot;5&quot; is the value.
+
+<p><b>xmlrpc</b> is capable of only a subset of the 
+possible XML-RPC types, as follows by prefix:
+
+<dl>
+<dt>i/
+<dd>integer (&lt;int4&gt;)
+
+<dt>s/
+<dd>string (&lt;string&gt;)
+
+<dt>b/
+<dd>boolean (&lt;boolean&gt;)
+
+<dt>d/
+<dd>double (&lt;double&gt;)  (i.e. real number)
+
+<dt>n/
+<dd>nil (&lt;nil&gt;)
+
+</dl>
+
+<p>As a shortcut, if you don't specify a prefix (i.e. your argument does
+not contain a slash), <b>xmlrpc</b> assumes string data type.
+
+</dl>
+
+
+<h2>Options</h2>
+
+<dl>
+<dt><b>-transport=</b><i>transportname</i>
+
+<dd>This selects the XML transport facility (e.g. libwww) that
+<b>xmlrpc</b> uses to perform the RPC.
+
+<p>The name <i>transportname</i> is one that the Xmlrpc-c programming
+library recognizes.  This is typically <b>libwww</b>, <b>curl</b>, and
+<b>wininet</b>.
+
+<p>By default, <b>xmlrpc</b> lets the Xmlrpc-c library choose.
+
+<dt><b>-username=</b><i>username</i>
+<dt><b>-password=</b><i>password</i>
+
+<dd>These options, which must be used together, cause the client to
+authenticate itself to the server, if the server requires it, using
+HTTP Basic Authentication and the specified username and password.
+
+<dt><b>-curlinterface</b>={<i>interface</i>|<i>host</i>}
+
+<dd>
+This option gives the &quot;interface&quot; option for a Curl XML transport.
+
+<p>The exact meaning of this option is up to the Curl library, and the
+best documentation for it is the manual for the 'curl' program that comes
+with the Curl library.
+
+<p>But essentially, it chooses the local network interface through which
+to send the RPC.  It causes the Curl library to perform a
+&quot;bind&quot; operation on the socket it uses for the
+communication.  It can be the name of a network interface (e.g. on
+Linux, &quot;eth1&quot;) or an IP address of the interface or a host
+name that resolves to the IP address of the interface.  Unfortunately,
+you can't explicitly state which form you're specifying, so there's
+some ambiguity.
+
+<p>Examples:
+
+<ul>
+
+<li>
+<kbd>
+-interface=eth1
+</kbd>
+
+<li>
+<kbd>
+-interface=64.171.19.66
+</kbd>
+
+<li>
+<kbd>
+-interface=giraffe.giraffe-data.com
+</kbd>
+
+</ul>
+
+<p>This option causes <b>xmlrpc</b> to default to using the Curl
+XML transport.  You may not specify any other transport.
+
+<dt><b>-curlnoverifypeer</b>
+
+<dd>
+This option gives the &quot;no_ssl_verifypeer&quot; option for the Curl
+XML transport, which is essentially the CURLOPT_SSL_VERIFYPEER option
+of the Curl library.
+
+<p>See the <b>curl_easy_setopt()</b> man page for details on this, but
+essentially it means that the client does not authenticate the server's
+certificate of identity -- it just believes whatever the server says.
+
+<p>You may want to use <b>-curlnoverifyhost</b> as well.  Since you're
+not authenticating the server's identity, there's not much sense in
+checking it.
+
+<p>This option causes <b>xmlrpc</b> to default to using the Curl
+XML transport.  You may not specify any other transport.
+
+
+<dt><b>-curlnoverifyhost</b>
+
+<dd>
+This option gives the &quot;no_ssl_verifyhost&quot; option for the Curl
+XML transport, which is essentially the CURLOPT_SSL_VERIFYHOST option
+of the Curl library.
+
+<p>See the <b>curl_easy_setopt()</b> man page for details on this, but
+essentially it means that the client does not verify the server's
+identity.  It just assumes that if the server answers the IP address
+of the server as indicated by the URL (probably via host name), then
+it's the intended server.
+
+<p>You may want to use <b>-curlnoverifypeer</b> as well.  As long as
+you don't care who the server says it is, there's no point in
+authenticating its identity.
+
+<p>This option causes <b>xmlrpc</b> to default to using the Curl
+XML transport.  You may not specify any other transport.
+
+
+</dl>
+
+</body>
diff --git a/tools/xmlrpc_transport/.cvsignore b/tools/xmlrpc_transport/.cvsignore
new file mode 100644 (file)
index 0000000..bff9884
--- /dev/null
@@ -0,0 +1 @@
+xmlrpc_transport
diff --git a/tools/xmlrpc_transport/Makefile b/tools/xmlrpc_transport/Makefile
new file mode 100644 (file)
index 0000000..a6112ae
--- /dev/null
@@ -0,0 +1,64 @@
+ifeq ($(SRCDIR)x,x)
+SRCDIR = $(CURDIR)/../..
+endif
+# BLDDIR is for use in places where a symbolic link won't work.
+# BUILDDIR is for places in Makefile.common that can use the 'blddir'
+# symbolic link (but in other directories, doesn't).
+BLDDIR = $(SRCDIR)
+BUILDDIR = blddir
+
+default: all
+
+include $(BLDDIR)/Makefile.config
+
+PROGRAMS_TO_INSTALL = xmlrpc_transport
+
+include ../Makefile.common
+
+INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include
+
+CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD)
+
+LDFLAGS = $(LADD)
+
+all: xmlrpc_transport
+
+UTIL_OBJS = cmdline_parser.o getoptx.o casprintf.o
+UTILS = $(UTIL_OBJS:%=$(UTIL_DIR)/%)
+
+# These are the Libtool .la files.  We use them only for make dependencies.
+# We'd like to use these in the link rule, by using libtool --link, but
+# Libtool adds -l options to the link to cover the dependencies that are
+# recorded inside the shared libraries.  And it doesn't add the necessary
+# -L options (it can't), so we end up with a messy mixture of the two
+# forms of specifying libraries.
+
+LIBS = $(LIBXMLRPC_CLIENT) $(LIBXMLRPC) $(LIBXMLRPC_XML) $(LIBXMLRPC_UTIL)
+
+xmlrpc_transport:%:%.o $(LIBS) $(UTILS)
+       $(CCLD) -o $@ $(LDFLAGS) $< $(CLIENT_LDLIBS) $(UTILS)
+
+%.o:%.c
+       $(CC) -c $(CFLAGS) $<
+
+*.c: config.h
+
+config.h:
+       $(LN_S) $(BLDDIR)/xmlrpc_config.h $@
+
+# This Makefile.config dependency makes sure the symlinks get built before
+# this make file is used for anything.
+
+$(BLDDIR)/Makefile.config: blddir srcdir
+
+include Makefile.depend
+
+.PHONY: dep
+dep: dep-common
+
+.PHONY: clean
+clean: clean-common
+       rm -f xmlrpc_transport config.h
+
+.PHONY: distclean
+distclean: clean distclean-common
diff --git a/tools/xmlrpc_transport/Makefile.depend b/tools/xmlrpc_transport/Makefile.depend
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/xmlrpc_transport/xmlrpc_transport.c b/tools/xmlrpc_transport/xmlrpc_transport.c
new file mode 100644 (file)
index 0000000..ad0c7de
--- /dev/null
@@ -0,0 +1,289 @@
+/* Transport some XML to a server and get the response back, as if doing
+   an XML-RPC call.
+*/
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"  /* information about this build environment */
+#include "casprintf.h"
+#include "mallocvar.h"
+#include "cmdline_parser.h"
+
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/client.h"
+
+#define NAME "xmlrpc_transport command line program"
+#define VERSION "1.0"
+
+struct cmdlineInfo {
+    const char *  url;
+    const char *  username;
+    const char *  password;
+    const char *  transport;
+        /* Name of XML transport he wants to use.  NULL if he has no 
+           preference.
+        */
+};
+
+
+
+static void 
+die_if_fault_occurred (xmlrpc_env * const envP) {
+    if (envP->fault_occurred) {
+        fprintf(stderr, "Error: %s (%d)\n",
+                envP->fault_string, envP->fault_code);
+        exit(1);
+    }
+}
+
+
+
+static void GNU_PRINTF_ATTR(2,3)
+setError(xmlrpc_env * const envP, const char format[], ...) {
+    va_list args;
+    const char * faultString;
+
+    va_start(args, format);
+
+    cvasprintf(&faultString, format, args);
+    va_end(args);
+
+    xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, faultString);
+
+    strfree(faultString);
+}
+      
+
+
+static void
+processArguments(xmlrpc_env *         const envP,
+                 cmdlineParser        const cp,
+                 struct cmdlineInfo * const cmdlineP) {
+
+    if (cmd_argumentCount(cp) < 1)
+        setError(envP, "Not enough arguments.  Need a URL.");
+    else {
+        cmdlineP->url = cmd_getArgument(cp, 0);
+    }
+}
+
+
+
+static void
+parseCommandLine(xmlrpc_env *         const envP,
+                 int                  const argc,
+                 const char **        const argv,
+                 struct cmdlineInfo * const cmdlineP) {
+
+    cmdlineParser const cp = cmd_createOptionParser();
+
+    const char * error;
+
+    cmd_defineOption(cp, "transport", OPTTYPE_STRING);
+    cmd_defineOption(cp, "username",  OPTTYPE_STRING);
+    cmd_defineOption(cp, "password",  OPTTYPE_STRING);
+
+    cmd_processOptions(cp, argc, argv, &error);
+
+    if (error) {
+        setError(envP, "Command syntax error.  %s", error);
+        strfree(error);
+    } else {
+        cmdlineP->username  = cmd_getOptionValueString(cp, "username");
+        cmdlineP->password  = cmd_getOptionValueString(cp, "password");
+
+        if (cmdlineP->username && !cmdlineP->password)
+            setError(envP, "When you specify -username, you must also "
+                     "specify -password.");
+        else {
+            cmdlineP->transport = cmd_getOptionValueString(cp, "transport");
+            
+            processArguments(envP, cp, cmdlineP);
+        }
+    }
+    cmd_destroyOptionParser(cp);
+}
+
+
+
+static void
+freeCmdline(struct cmdlineInfo const cmdline) {
+
+    strfree(cmdline.url);
+    if (cmdline.username)
+        strfree(cmdline.username);
+    if (cmdline.password)
+        strfree(cmdline.password);
+    if (cmdline.transport)
+        strfree(cmdline.transport);
+}
+
+
+
+static void
+computeUrl(const char *  const urlArg,
+           const char ** const urlP) {
+
+    if (strstr(urlArg, "://") != 0) {
+        *urlP = strdup(urlArg);
+    } else {
+        casprintf(urlP, "http://%s/RPC2", urlArg);
+    }        
+}
+
+
+
+static void
+doCall(xmlrpc_env *               const envP,
+       const char *               const transport,
+       const xmlrpc_server_info * const serverInfoP,
+       xmlrpc_mem_block *         const callXmlP,
+       xmlrpc_mem_block **        const respXmlPP) {
+    
+    struct xmlrpc_clientparms clientparms;
+
+    clientparms.transport = transport;
+
+    clientparms.transportparmsP = NULL;
+    clientparms.transportparm_size = 0;
+
+    xmlrpc_client_init2(envP, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, 
+                        &clientparms, XMLRPC_CPSIZE(transportparm_size));
+    if (!envP->fault_occurred) {
+        xmlrpc_client_transport_call(envP, NULL, serverInfoP,
+                                     callXmlP, respXmlPP);
+        
+        xmlrpc_client_cleanup();
+    }
+}
+
+
+
+static void
+createServerInfo(xmlrpc_env *          const envP,
+                 const char *          const serverUrl,
+                 const char *          const userName,
+                 const char *          const password,
+                 xmlrpc_server_info ** const serverInfoPP) {
+
+    xmlrpc_server_info * serverInfoP;
+
+    serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
+    if (!envP->fault_occurred) {
+        if (userName) {
+            xmlrpc_server_info_set_basic_auth(
+                envP, serverInfoP, userName, password);
+        }
+    }
+    *serverInfoPP = serverInfoP;
+}
+
+
+
+static void
+readFile(xmlrpc_env *        const envP,
+         FILE *              const ifP,
+         xmlrpc_mem_block ** const fileContentsPP) {
+
+    xmlrpc_mem_block * fileContentsP;
+
+    fileContentsP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
+
+    while (!envP->fault_occurred && !feof(ifP)) {
+        char buffer[4096];
+        size_t bytesRead;
+        
+        bytesRead = fread(buffer, 1, sizeof(buffer), ifP);
+        XMLRPC_MEMBLOCK_APPEND(char, envP, 
+                               fileContentsP, buffer, bytesRead);
+    }
+    if (envP->fault_occurred)
+        XMLRPC_MEMBLOCK_FREE(char, fileContentsP);
+
+    *fileContentsPP = fileContentsP;
+}
+
+
+
+static void
+writeFile(xmlrpc_env *       const envP,
+          FILE *             const ofP,
+          xmlrpc_mem_block * const fileContentsP) {
+
+    size_t totalWritten;
+
+    totalWritten = 0;
+
+    while (!envP->fault_occurred &&
+           totalWritten < XMLRPC_MEMBLOCK_SIZE(char, fileContentsP)) {
+        size_t bytesWritten;
+
+        bytesWritten = fwrite(
+            XMLRPC_MEMBLOCK_CONTENTS(char, fileContentsP) + totalWritten,
+            1,
+            XMLRPC_MEMBLOCK_SIZE(char, fileContentsP) - totalWritten,
+            ofP);
+
+        if (bytesWritten < 1)
+            xmlrpc_env_set_fault_formatted(
+                envP, XMLRPC_INTERNAL_ERROR,
+                "Error writing output");
+
+        totalWritten -= bytesWritten;
+    }
+}
+
+
+
+int 
+main(int           const argc, 
+     const char ** const argv) {
+
+    struct cmdlineInfo cmdline;
+    xmlrpc_env env;
+    xmlrpc_mem_block * callXmlP;
+    xmlrpc_mem_block * respXmlP;
+    const char * url;
+    xmlrpc_server_info * serverInfoP;
+
+    xmlrpc_env_init(&env);
+
+    parseCommandLine(&env, argc, argv, &cmdline);
+    die_if_fault_occurred(&env);
+
+    computeUrl(cmdline.url, &url);
+
+    createServerInfo(&env, url, cmdline.username, cmdline.password,
+                     &serverInfoP);
+    die_if_fault_occurred(&env);
+
+    fprintf(stderr, "Reading call data from Standard Input...\n");
+
+    readFile(&env, stdin, &callXmlP);
+    die_if_fault_occurred(&env);
+
+    fprintf(stderr, "Making call...\n");
+
+    doCall(&env, cmdline.transport, serverInfoP, callXmlP,
+           &respXmlP);
+    die_if_fault_occurred(&env);
+
+    fprintf(stderr, "Writing response data to Standard Output\n");
+    writeFile(&env, stdout, respXmlP);
+    die_if_fault_occurred(&env);
+
+    XMLRPC_MEMBLOCK_FREE(char, callXmlP);
+    XMLRPC_MEMBLOCK_FREE(char, respXmlP);
+    
+    strfree(url);
+
+    freeCmdline(cmdline);
+
+    xmlrpc_env_clean(&env);
+    
+    return 0;
+}
diff --git a/tools/xmlrpc_transport/xmlrpc_transport.html b/tools/xmlrpc_transport/xmlrpc_transport.html
new file mode 100644 (file)
index 0000000..4610fef
--- /dev/null
@@ -0,0 +1,95 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<title>Xmlrpc_transport User Manual</title>
+<body>
+
+<p><b>xmlrpc_transport</b> transports data to a server as if to make an
+XML-RPC remote procedure call and displays the response from the server.
+
+<p>You supply the call in XML form on Standard Input and get the response
+in XML form on Standard Output.  <b>xmlrpc_transport</b> doesn't really know
+anything about XML; it sends the characters you supply and displays the
+characters it gets back.
+
+<p><b>xmlrpc_transport</b> uses the lower levels of the XML-RPC For C/C++
+client libraries.
+
+<p>This program is mainly useful for debugging and learning about
+XML-RPC servers and the XML-RPC For C/C++ client XML transports.
+
+
+<h2>Examples</h2>
+
+&lt;
+
+<pre>
+<tt>
+     $ xmlrpc_transport http://localhost:8080/RPC2 &lt;&lt;-EOF
+        &lt;?xml version="1.0" encoding="UTF-8"?&gt;
+        &lt;methodCall&gt;
+        &lt;methodName&gt;sample.add&lt;/methodName&gt;
+        &lt;params&gt;
+        &lt;param&gt;&lt;value&gt;&lt;i4&gt;5&lt;/i4&gt;&lt;/value&gt;&lt;/param&gt;
+        &lt;param&gt;&lt;value&gt;&lt;i4&gt;7&lt;/i4&gt;&lt;/value&gt;&lt;/param&gt;
+        &lt;/params&gt;
+        &lt;/methodCall&gt;
+        EOF
+     &lt;?xml version="1.0" encoding="UTF-8"?&gt;
+     &lt;methodResponse&gt;
+     &lt;params&gt;
+     &lt;param&gt;&lt;value&gt;&lt;i4&gt;12&lt;/i4&gt;&lt;/value&gt;&lt;/param&gt;
+     &lt;/params&gt;
+     &lt;/methodResponse&gt;
+</tt>
+</pre>
+
+<h2>Overview</h2>
+<p>
+<b>xmlrpc_transport</b>
+<i>url</i>
+[<b>-transport=</b><i>transportname</i>]
+[<b>-username=</b><i>username</i> <b>-password=</b><i>password</i>]
+
+<P>Minimum unique abbreviation of option is acceptable.  You may use double
+hyphens instead of single hyphen to denote options.  You may use white
+space in place of the equals sign to separate an option name from its value.
+
+
+<h2>Arguments</h2>
+
+<dl>
+<dt><i>url</i>
+
+<dd>This is the URL of the XML-RPC server.  As XML-RPC uses HTTP, this
+must be an HTTP url.  However, if you don't specify a type (&quot;http:&quot;)
+in the URL, <b>xmlrpc_transport</b> assumes an &quot;http://&quot; prefix and a
+&quot;/RPC2&quot; suffix.  <b>RPC2</b> is the conventional file name for
+an XML-RPC responder.
+
+</dl>
+
+
+<h2>Options</h2>
+
+<dl>
+<dt><b>-transport=</b><i>transportname</i>
+
+<dd>This selects the XML transport facility (e.g. libwww) that
+<b>xmlrpc_transport</b> uses to perform the RPC.
+
+<p>The name <i>transportname</i> is one that the Xmlrpc-c programming
+library recognizes.  This is typically <b>libwww</b>, <b>curl</b>, and
+<b>wininet</b>.
+
+<p>By default, <b>xmlrpc_transport</b> lets the Xmlrpc-c library choose.
+
+<dt><b>-username=</b><i>username</i>
+<dt><b>-password=</b><i>password</i>
+
+<dd>These options, which must be used together, cause the client to
+authenticate itself to the server, if the server requires it, using
+HTTP Basic Authentication and the specified username and password.
+
+</dl>
+
+</body>
+
diff --git a/unix-common.make b/unix-common.make
new file mode 100644 (file)
index 0000000..276866a
--- /dev/null
@@ -0,0 +1,71 @@
+# -*-makefile-*-    <-- an Emacs control
+
+# The including make file must define these make variables:
+#
+# SHARED_LIBS_TO_INSTALL: List of the shared libraries that need to be
+#   installed -- just the basic library names.  E.g. "libfoo libbar"
+#
+# SHLIB_SUFFIX: Shared library filename suffix, e.g. "so".
+#
+# MAJ: Library major version number, e.g. "3" in file name "libfoo.3.1"
+#
+# MIN: Library minor version number, e.g. "1" in file name "libfoo.3.1"
+#
+# LDFLAGS_SHLIB: linker (Ld) flags needed to link object files together into
+#   a shared library.  May use $(SONAME) for the soname of the library.
+#   Include -lc if appropriate.
+#
+# LADD: Additional linker flags (normally set on the make command line).
+#
+# INSTALL_DATA: beginning of shell command to install a library file.
+#
+# DESTDIR: main installation directory
+#
+# LIBINST_DIR: directory in which to install libraries, relative to DESTDIR.
+#
+# LN_S: beginning of shell command to make symbolic link (e.g. "ln -s").
+#
+# CXXLD: beginning of shell command to link, e.g. "g++".
+
+# This make file defines these make variables that the including make file
+# can use:
+#
+# ALL_SHARED_LIBRARIES: list of targets to be dependencies of all: .
+
+# Including make file must contain a rule to build each library file
+# (e.g. libfoo.3.1)
+
+# This make file provides these rules:
+#
+# install-shared-libraries: install all shared libraries and the necessary
+# symbolic links.
+
+ALL_SHARED_LIBRARIES = \
+  $(SHARED_LIBS_TO_BUILD:%=%.$(SHLIB_SUFFIX).$(MAJ).$(MIN))
+
+# SONAME is to be referenced by $(LDSHLIB) in $(SHLIB_RULE)
+# SONAME is the name of the library file being built, with the minor
+#   version number cut off.  E.g. if we're building libfoo.so.1.2, SONAME
+#   is libfoo.so.1 .
+SONAME = $(@:%.$(MIN)=%)
+
+SHLIB_RULE = $(CXXLD) $(LDFLAGS_SHLIB) -o $@ $^ $(LADD)
+
+SHLIB_INSTALL_TARGETS = $(SHARED_LIBS_TO_INSTALL:%=%/install)
+
+#SHLIB_INSTALL_TARGETS is like "install/libfoo install/libbar"
+
+.PHONY: $(SHLIB_INSTALL_TARGETS)
+.PHONY: install-shared-libraries
+
+install-shared-libraries: $(SHLIB_INSTALL_TARGETS)
+
+$(SHLIB_INSTALL_TARGETS) X/install:%/install:%.$(SHLIB_SUFFIX).$(MAJ).$(MIN)
+# $< is a library file name, e.g. libfoo.3.1 .
+       $(INSTALL_SHLIB) $< $(DESTDIR)$(LIBINST_DIR)/$<
+       cd $(DESTDIR)$(LIBINST_DIR); \
+         rm -f $(<:%.$(MIN)=%); \
+          $(LN_S) $< $(<:%.$(MIN)=%)
+       cd $(DESTDIR)$(LIBINST_DIR); \
+         rm -f $(<:%.$(MAJ).$(MIN)=%); \
+          $(LN_S) $(<:%.$(MIN)=%) $(<:%.$(MAJ).$(MIN)=%)
diff --git a/xmlrpc-c-config.in b/xmlrpc-c-config.in
new file mode 100644 (file)
index 0000000..80b84d8
--- /dev/null
@@ -0,0 +1,178 @@
+#!/bin/sh
+# Stolen from rep-config and adapted for use with xmlrpc-c.
+# Other bits stolen from gnome-config & automake output.
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+
+bindir="@bindir@"
+datadir="@datadir@"
+libdir="@libdir@"
+includedir="@includedir@"
+
+ENABLE_LIBXML2_BACKEND='@ENABLE_LIBXML2_BACKEND@'
+ENABLE_ABYSS_THREADS='@ENABLE_ABYSS_THREADS@'
+MUST_BUILD_CURL_CLIENT='@MUST_BUILD_CURL_CLIENT@'
+MUST_BUILD_WININET_CLIENT='@MUST_BUILD_WININET_CLIENT@'
+MUST_BUILD_LIBWWW_CLIENT='@MUST_BUILD_LIBWWW_CLIENT@'
+LSOCKET='@LSOCKET@'
+
+usage="Usage: xmlrpc-c-config <feature> ... <option> ...
+
+The features are:
+  c++            legacy C++ wrapper API
+  c++2           modern C++ API
+  client         client functions
+  cgi-server     CGI-based server functions
+  abyss-server   ABYSS-based server functions
+  server-util    basic server functions (implied by *-server)
+
+Options are:
+  --version      The version number of the package
+  --features     List all features (aka modules) currently installed
+  --cflags       C compiler flags to use when '#include'ing package headers
+  --libs         Libraries and flags to use when linking programs normally
+  --ldadd        Libraries to use with automake
+  --ldflags      Flags to use with automake & libtool
+  --prefix       The prefix under which the package was installed
+  --exec-prefix  The executable prefix under which the package was installed
+  --*dir         The various directories under which the package was installed"
+
+if test $# -eq 0; then
+      echo "You must specify at least one option."
+      echo "${usage}" 1>&2
+      exit 1
+fi
+
+if test "${ENABLE_LIBXML2_BACKEND}" = "yes"; then
+  LIBXML=`xml2-config --libs`
+else
+  LIBXML="-lxmlrpc_xmlparse -lxmlrpc_xmltok"
+fi
+
+needCpp=no
+
+the_libdirs=
+
+# If Xmlrpc-c libraries are installed in the standard linker search
+# path on this system, you should remove the following line:
+the_libdirs="-L$libdir $the_libdirs"
+
+the_libs="-lxmlrpc -lxmlrpc_util ${LIBXML}"
+the_rpath=
+the_wl_rpath=
+cpp_libs=
+
+cflags=
+# If Xmlrpc-c library interface header files are installed in the standard
+# compiler search path on this system, you should remove the following line:
+cflags="-I$includedir $cflags"
+
+while test $# -gt 0; do
+  case $1 in
+    c++)
+      the_libs="-lxmlrpc_cpp $the_libs"
+
+      # Unfortunately, there is just one legacy CPP library for
+      # everything, and it needs all the C libraries -- base, client,
+      # and server.  So all legacy C++ programs get linked with client
+      # and server libraries, whether they need them or not.
+
+      the_libs="-lxmlrpc_server_abyss $the_libs"
+      the_libs="-lxmlrpc_server $the_libs"
+      the_libs="-lxmlrpc_client $the_libs"
+      ;;
+    c++2)
+      needCpp=yes
+      the_libs="-lxmlrpc++ $the_libs"
+      ;;
+    server-util)
+      the_libs="-lxmlrpc_server $the_libs"
+      ;;
+    cgi-server)
+      the_libs="-lxmlrpc_server $the_libs"
+      the_libs="-lxmlrpc_server_cgi $the_libs"
+      ;;
+    abyss-server)
+      if test "${ENABLE_ABYSS_THREADS}" = "yes"; then
+        the_libs="-lpthread $the_libs"
+        fi
+      the_libs="${LSOCKET} $the_libs"
+      the_libs="-lxmlrpc_abyss $the_libs"
+      the_libs="-lxmlrpc_server $the_libs"
+      the_libs="-lxmlrpc_server_abyss $the_libs"
+      if test "${needCpp}" = "yes"; then
+        the_libs="-lxmlrpc_server++ $the_libs"
+        the_libs="-lxmlrpc_server_abyss++ $the_libs"
+        fi
+      ;;
+    client|libwww-client)
+      # libwww-client is for backward compatibility
+      the_libs="-lxmlrpc_client $the_libs"
+
+      if test "${MUST_BUILD_WININET_CLIENT}" = "yes"; then
+        the_libs="@WININET_LDADD@ $the_libs"
+        the_rpath="@WININET_RPATH@ $the_rpath"
+        the_wl_rpath="@WININET_WL_RPATH@ $the_wl_rpath"
+      fi
+      if test "${MUST_BUILD_CURL_CLIENT}" = "yes"; then
+        the_libs="@CURL_LDADD@ $the_libs"
+        the_rpath="@CURL_RPATH@ $the_rpath"
+        the_wl_rpath="@CURL_WL_RPATH@ $the_wl_rpath"
+      fi
+      if test "${MUST_BUILD_LIBWWW_CLIENT}" = "yes"; then
+        the_libs="@LIBWWW_LDADD@ $the_libs"
+        the_rpath="@LIBWWW_RPATH@ $the_rpath"
+        the_wl_rpath="@LIBWWW_WL_RPATH@ $the_wl_rpath"
+      fi
+      if test "${needCpp}" = "yes"; then
+        the_libs="-lxmlrpc_client++ $the_libs"
+        fi
+      ;;
+    --version)
+      echo "@VERSION@"
+      ;;
+    --modules)
+      echo "@FEATURE_LIST@"
+      ;;
+    --features)
+      echo "@FEATURE_LIST@"
+      ;;
+    --cflags)
+      echo "$cflags"
+      ;;
+    --libs)
+      echo "$the_libdirs $the_libs $the_wl_rpath"
+      ;;
+    --ldadd)
+      echo "$the_libdirs $the_libs"
+      ;;
+    --ldflags)
+      echo "$the_rpath"
+      ;;
+    --prefix)
+      echo "@prefix@"
+      ;;
+    --exec-prefix)
+      echo "@exec_prefix@"
+      ;;
+    --*dir)
+      # Swiped from gnome-config.
+      dirname=\$`echo $1 | sed -e 's,^--,,'`
+      dirname=`eval echo $dirname`
+      test -z "$dirname" && exit 1
+      echo $dirname
+      ;;
+    --help)
+      echo "${usage}" 1>&2
+      ;;
+    *)
+      echo "Unrecognized token '$1'"
+      echo "${usage}" 1>&2
+      exit 1
+      ;;
+  esac
+  shift
+done
+
+exit 0
diff --git a/xmlrpc-c-config.test.in b/xmlrpc-c-config.test.in
new file mode 100644 (file)
index 0000000..50c00b4
--- /dev/null
@@ -0,0 +1,155 @@
+#!/bin/sh
+# This is like 'xmlrpc-c-config', but for testing Xmlrpc-c from its build
+# directory instead of for an installed instance of Xmlrpc-c.
+#
+# For example, the make file in the examples/ directory uses this program
+# to link the example programs with the Xmlrpc-c libraries in the build
+# directory.  A real application program would instead use xmlrpc-c-config
+# and get the Xmlrpc-c libraries from their installed home.
+
+# @srcdir@ and @top_srcdir@ are useless because they can be relative.
+
+SRCDIR="@BUILDDIR@"  # until we figure out how to do it right
+BUILDDIR="@BUILDDIR@"
+ENABLE_LIBXML2_BACKEND="@ENABLE_LIBXML2_BACKEND@"
+ENABLE_ABYSS_THREADS="@ENABLE_ABYSS_THREADS@"
+MUST_BUILD_CURL_CLIENT="@MUST_BUILD_CURL_CLIENT@"
+MUST_BUILD_WININET_CLIENT="@MUST_BUILD_WININET_CLIENT@"
+MUST_BUILD_LIBWWW_CLIENT="@MUST_BUILD_LIBWWW_CLIENT@"
+LSOCKET="@LSOCKET@"
+
+if test $# -eq 0; then
+      echo "You need to specify arguments"
+      exit 1
+fi
+
+sopath=
+
+if test "${ENABLE_LIBXML2_BACKEND}" = "yes"; then
+  LIBXML=`xml2-config --libs`
+else
+  LIBXML="${BUILDDIR}/lib/expat/xmlparse/.libs/libxmlrpc_xmlparse.a"
+  sopath="${BUILDDIR}/lib/expat/xmlparse/.libs:$sopath"
+  LIBXML="${LIBXML} ${BUILDDIR}/lib/expat/xmltok/.libs/libxmlrpc_xmltok.a"
+  sopath="${BUILDDIR}/lib/expat/xmltok/.libs:$sopath"
+fi
+
+needCpp=no
+
+LIBXMLRPC="${BUILDDIR}/src/.libs/libxmlrpc.a"
+LIBXMLRPC_UTIL="${BUILDDIR}/lib/libutil/.libs/libxmlrpc_util.a"
+
+the_libs="${LIBXMLRPC} ${LIBXMLRPC_UTIL} ${LIBXML}"
+the_includes="-I${SRCDIR}/include"
+sopath="${BUILDDIR}/src/.libs:$sopath"
+
+while test $# -gt 0; do
+  case $1 in
+    c++)
+      # Unfortunately, there is just one legacy CPP library for
+      # everything, and it needs all the C libraries -- base, client,
+      # and server.  So all legacy C++ programs get linked with client
+      # and server libraries, whether they need them or not.
+
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_server.a $the_libs"
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_server_abyss.a $the_libs"
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_client.a $the_libs"
+      the_libs="${BUILDDIR}/src/cpp/libxmlrpc_cpp.a $the_libs"
+      ;;
+    c++2)
+      needCpp=yes
+      the_libs="${BUILDDIR}/src/cpp/libxmlrpc++.a $the_libs"
+      ;;
+    server-util)
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_server.a $the_libs"
+      ;;
+    cgi-server)
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_server.a $the_libs"
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_server_cgi.a $the_libs"
+      ;;
+    abyss-server)
+      if test "${ENABLE_ABYSS_THREADS}" = "yes"; then
+        the_libs="-lpthread $the_libs"
+        fi
+      the_libs="${LSOCKET} $the_libs"
+      the_libs="${BUILDDIR}/lib/abyss/src/.libs/libxmlrpc_abyss.a $the_libs"
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_server.a $the_libs"
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_server_abyss.a $the_libs"
+      if test "${needCpp}" = "yes"; then
+        the_libs="${BUILDDIR}/src/cpp/libxmlrpc_server++.a $the_libs"
+        the_libs="${BUILDDIR}/src/cpp/libxmlrpc_server_abyss++.a $the_libs"
+        fi
+      the_includes="-I${SRCDIR}/lib/abyss/src $the_includes"
+      sopath="${BUILDDIR}/lib/abyss/src/.libs:$sopath"
+      ;;
+    client)
+      the_libs="${BUILDDIR}/src/.libs/libxmlrpc_client.a $the_libs"
+      if test "${MUST_BUILD_WININET_CLIENT}" = "yes"; then
+        the_libs="@WININET_LDADD@ $the_libs"
+        the_rpath="@WININET_RPATH@ $the_rpath"
+        the_wl_rpath="@WININET_WL_RPATH@ $the_wl_rpath"
+        fi
+      if test "${MUST_BUILD_CURL_CLIENT}" = "yes"; then
+        the_libs="@CURL_LDADD@ $the_libs"
+        the_rpath="@CURL_RPATH@ $the_rpath"
+        the_wl_rpath="@CURL_WL_RPATH@ $the_wl_rpath"
+        fi
+      if test "${MUST_BUILD_LIBWWW_CLIENT}" = "yes"; then
+        the_libs="@LIBWWW_LDADD@ $the_libs"
+        the_rpath="@LIBWWW_RPATH@ $the_rpath"
+        the_wl_rpath="@LIBWWW_WL_RPATH@ $the_wl_rpath"
+        fi
+      if test "${needCpp}" = "yes"; then
+        the_libs="${BUILDDIR}/src/cpp/libxmlrpc_client++.a $the_libs"
+        fi
+      ;;
+    --version)
+      echo "@VERSION@"
+      ;;
+    --modules)
+      echo "@FEATURE_LIST@"
+      ;;
+    --features)
+      echo "@FEATURE_LIST@"
+      ;;
+    --cflags)
+      echo "$the_includes"
+      ;;
+    --libs)
+      echo "$the_libdirs $the_libs $the_wl_rpath"
+      ;;
+    --ldadd)
+      echo "$the_libdirs $the_libs"
+      ;;
+    --ldflags)
+      echo "$the_rpath"
+      ;;
+    --sopath)
+      echo "$sopath"
+      ;;
+    --prefix)
+      echo "@prefix@"
+      ;;
+    --exec-prefix)
+      echo "@exec_prefix@"
+      ;;
+    --*dir)
+      # Swiped from gnome-config.
+      dirname=\$`echo $1 | sed -e 's,^--,,'`
+      dirname=`eval echo $dirname`
+      test -z "$dirname" && exit 1
+      echo $dirname
+      ;;
+    --help)
+      echo "See the real xmlrpc-c-config program" 1>&2
+      ;;
+    *)
+      echo "Unrecognized token '$1'"
+      echo "${usage}" 1>&2
+      exit 1
+      ;;
+  esac
+  shift
+done
+
+exit 0
diff --git a/xmlrpc_amconfig.h.in b/xmlrpc_amconfig.h.in
new file mode 100644 (file)
index 0000000..388161a
--- /dev/null
@@ -0,0 +1,23 @@
+/* xmlrpc_amconfig.h is generated by 'configure' from the template
+   xmlrpc_amconfig.h.in, by virtue of the AM_CONFIG_HEADER() macro in
+   configure.in.
+
+   In the future, we plan to eliminate this file, because it is a special
+   tool that requires extra learning.  Instead, we will just put logic
+   directly in configure.in like that for wchar.h, etc.
+*/
+
+/* The following are related to AC_CHECK_FUNCS macro calls in
+   configure.in
+*/
+
+#undef HAVE_SETGROUPS
+#undef HAVE_ASPRINTF
+#undef HAVE_SETENV
+#undef HAVE_WCSNCMP
+
+/* Define if you have the socket library (-lsocket).  */
+#undef HAVE_LIBSOCKET
+
+/* Name of package */
+#undef PACKAGE
diff --git a/xmlrpc_config.h.in b/xmlrpc_config.h.in
new file mode 100644 (file)
index 0000000..e090777
--- /dev/null
@@ -0,0 +1,50 @@
+/* xmlrpc_config.h is generated from xmlrpc_config.h.in by 'configure'.
+
+   This file just uses plain AC_SUBST substitution, the same as
+   Makefile.config.  Wherever you see @XXX@, that gets replaced by the
+   value of 'configure' variable XXX.
+
+   Logical macros are 0 or 1 instead of the more traditional defined and
+   undefined.  That's so we can distinguish when compiling code between
+   "false" and some problem with the code.
+*/
+
+
+/* We hope to replace xmlrpc_amconfig.h some day with something that 
+   doesn't require a whole special set of software to build, to make
+   Xmlrpc-c approachable by dumber developers.
+*/
+#include "xmlrpc_amconfig.h"
+
+
+#define HAVE_WCHAR_H @HAVE_WCHAR_H_DEFINE@
+#define HAVE_SYS_FILIO_H @HAVE_SYS_FILIO_H_DEFINE@
+#define HAVE_SYS_IOCTL_H @HAVE_SYS_IOCTL_H_DEFINE@
+
+#define VA_LIST_IS_ARRAY @VA_LIST_IS_ARRAY_DEFINE@
+
+#define HAVE_LIBWWW_SSL @HAVE_LIBWWW_SSL_DEFINE@
+
+#define ATTR_UNUSED @ATTR_UNUSED@
+
+#define DIRECTORY_SEPARATOR "@DIRECTORY_SEPARATOR@"
+
+#define HAVE_UNICODE_WCHAR HAVE_WCHAR_H
+
+/*  Xmlrpc-c code uses __inline__ to declare functions that should
+    be compiled as inline code.  GNU C recognizes the __inline__ keyword.
+    Others recognize 'inline' or '__inline' or nothing at all to say
+    a function should be inlined.
+
+    We could make 'configure' simply do a trial compile to figure out
+    which one, but for now, this approximation is easier:
+*/
+#if (!defined(__GNUC__))
+  #if (!defined(__inline__))
+    #if (defined(__sgi) || defined(_AIX))
+      #define __inline__ __inline
+    #else   
+      #define __inline__
+    #endif
+  #endif
+#endif