]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add tpl to tree (please check win build)
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 13 Sep 2012 20:01:01 +0000 (15:01 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 13 Sep 2012 20:01:01 +0000 (15:01 -0500)
661 files changed:
Makefile.am
libs/libtpl-1.5/LICENSE [new file with mode: 0755]
libs/libtpl-1.5/Makefile.am [new file with mode: 0755]
libs/libtpl-1.5/Makefile.in [new file with mode: 0644]
libs/libtpl-1.5/README [new file with mode: 0755]
libs/libtpl-1.5/bootstrap [new file with mode: 0755]
libs/libtpl-1.5/configure.ac [new file with mode: 0755]
libs/libtpl-1.5/doc/Makefile [new file with mode: 0755]
libs/libtpl-1.5/doc/NOTES [new file with mode: 0755]
libs/libtpl-1.5/doc/html/ChangeLog.html [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/banner.png [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/banner.svg [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/grad_azure.png [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/grad_azure.svg [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/rss.png [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/tpl-mini.png [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/tpl-mini.svg [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/tpl.dia [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/tpl.png [new file with mode: 0755]
libs/libtpl-1.5/doc/html/img/tpl_aai.dia [new file with mode: 0755]
libs/libtpl-1.5/doc/html/index.html [new file with mode: 0755]
libs/libtpl-1.5/doc/html/license.html [new file with mode: 0755]
libs/libtpl-1.5/doc/html/perl.html [new file with mode: 0755]
libs/libtpl-1.5/doc/html/styles.css [new file with mode: 0755]
libs/libtpl-1.5/doc/html/tdh-quirks.css [new file with mode: 0755]
libs/libtpl-1.5/doc/html/tdh.css [new file with mode: 0755]
libs/libtpl-1.5/doc/html/toc.css [new file with mode: 0755]
libs/libtpl-1.5/doc/html/userguide.html [new file with mode: 0755]
libs/libtpl-1.5/doc/pdf/userguide.pdf [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/ChangeLog.txt [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/compiling.txt [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/examples.txt [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/future.txt [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/perl.txt [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/sflogo.txt [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/toc.txt [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/topnav.txt [new file with mode: 0755]
libs/libtpl-1.5/doc/txt/userguide.txt [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/Tpl.pm [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/Makefile [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/README [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/client.pl [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/do_tests [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/server.pl [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test1 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test1.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test10 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test10.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test11 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test11.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test12 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test12.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test13 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test13.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test14 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test14.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test14.tpl [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test15 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test15.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test15.tpl [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test16 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test16.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test17 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test17.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test18 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test18.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test19 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test19.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test2 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test2.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test20 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test20.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test21 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test21.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test22 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test22.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test23 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test3 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test3.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test4 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test4.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test5 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test5.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test6 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test6.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test7 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test7.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test8 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test8.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test9 [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tests/test9.ans [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tplfmt [new file with mode: 0755]
libs/libtpl-1.5/lang/perl/tplxml [new file with mode: 0755]
libs/libtpl-1.5/src/Makefile.am [new file with mode: 0755]
libs/libtpl-1.5/src/Makefile.in [new file with mode: 0644]
libs/libtpl-1.5/src/tpl.c [new file with mode: 0755]
libs/libtpl-1.5/src/tpl.h [new file with mode: 0755]
libs/libtpl-1.5/src/win/Makefile.am [new file with mode: 0755]
libs/libtpl-1.5/src/win/Makefile.in [new file with mode: 0644]
libs/libtpl-1.5/src/win/README [new file with mode: 0755]
libs/libtpl-1.5/src/win/mman.h [new file with mode: 0755]
libs/libtpl-1.5/src/win/mmap.c [new file with mode: 0755]
libs/libtpl-1.5/src/win/nonempty.c [new file with mode: 0755]
libs/libtpl-1.5/tests/Makefile [new file with mode: 0755]
libs/libtpl-1.5/tests/Makefile.alt [new file with mode: 0755]
libs/libtpl-1.5/tests/Makefile.mingw [new file with mode: 0755]
libs/libtpl-1.5/tests/README [new file with mode: 0755]
libs/libtpl-1.5/tests/dbx.sh [new file with mode: 0755]
libs/libtpl-1.5/tests/do_tests [new file with mode: 0755]
libs/libtpl-1.5/tests/do_tests.cygwin [new file with mode: 0755]
libs/libtpl-1.5/tests/int64_align.c [new file with mode: 0755]
libs/libtpl-1.5/tests/malign.c [new file with mode: 0755]
libs/libtpl-1.5/tests/mgwtest.c [new file with mode: 0755]
libs/libtpl-1.5/tests/other/Makefile [new file with mode: 0755]
libs/libtpl-1.5/tests/other/README [new file with mode: 0755]
libs/libtpl-1.5/tests/other/do_tests [new file with mode: 0755]
libs/libtpl-1.5/tests/other/other1.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/other/other1.cpp [new file with mode: 0755]
libs/libtpl-1.5/tests/sizes [new file with mode: 0755]
libs/libtpl-1.5/tests/test1 [new file with mode: 0755]
libs/libtpl-1.5/tests/test1-mingw.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test1.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test1.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test1.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test10 [new file with mode: 0755]
libs/libtpl-1.5/tests/test10.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test10.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test10.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test10.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test100 [new file with mode: 0755]
libs/libtpl-1.5/tests/test100.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test100.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test100.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test101 [new file with mode: 0755]
libs/libtpl-1.5/tests/test101.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test101.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test101.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test102 [new file with mode: 0755]
libs/libtpl-1.5/tests/test102.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test102.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test102.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test103 [new file with mode: 0755]
libs/libtpl-1.5/tests/test103.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test103.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test103.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test104 [new file with mode: 0755]
libs/libtpl-1.5/tests/test104.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test104.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test104.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test105 [new file with mode: 0755]
libs/libtpl-1.5/tests/test105.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test105.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test105.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test106 [new file with mode: 0755]
libs/libtpl-1.5/tests/test106.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test106.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test106.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test107 [new file with mode: 0755]
libs/libtpl-1.5/tests/test107.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test107.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test107.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test108 [new file with mode: 0755]
libs/libtpl-1.5/tests/test108.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test108.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test108.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test109 [new file with mode: 0755]
libs/libtpl-1.5/tests/test109.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test109.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test109.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test11 [new file with mode: 0755]
libs/libtpl-1.5/tests/test11.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test11.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test11.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test11.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test110 [new file with mode: 0755]
libs/libtpl-1.5/tests/test110.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test110.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test110.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test111 [new file with mode: 0755]
libs/libtpl-1.5/tests/test111.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test111.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test111.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test112 [new file with mode: 0755]
libs/libtpl-1.5/tests/test112.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test112.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test112.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test113 [new file with mode: 0755]
libs/libtpl-1.5/tests/test113.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test113.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test113.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test114 [new file with mode: 0755]
libs/libtpl-1.5/tests/test114.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test114.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test114.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test115 [new file with mode: 0755]
libs/libtpl-1.5/tests/test115.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test115.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test115.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test116 [new file with mode: 0755]
libs/libtpl-1.5/tests/test116.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test116.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test116.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test117 [new file with mode: 0755]
libs/libtpl-1.5/tests/test117.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test117.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test117.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test118 [new file with mode: 0755]
libs/libtpl-1.5/tests/test118.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test118.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test118.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test119 [new file with mode: 0755]
libs/libtpl-1.5/tests/test119.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test119.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test119.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test12 [new file with mode: 0755]
libs/libtpl-1.5/tests/test12.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test12.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test12.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test12.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test120 [new file with mode: 0755]
libs/libtpl-1.5/tests/test120.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test120.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test120.err [new file with mode: 0644]
libs/libtpl-1.5/tests/test120.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test121 [new file with mode: 0755]
libs/libtpl-1.5/tests/test121.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test121.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test121.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test122 [new file with mode: 0755]
libs/libtpl-1.5/tests/test122.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test122.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test122.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test123 [new file with mode: 0755]
libs/libtpl-1.5/tests/test123.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test123.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test123.err [new file with mode: 0644]
libs/libtpl-1.5/tests/test123.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test124 [new file with mode: 0755]
libs/libtpl-1.5/tests/test124.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test124.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test124.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test13 [new file with mode: 0755]
libs/libtpl-1.5/tests/test13.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test13.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test13.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test13.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test14 [new file with mode: 0755]
libs/libtpl-1.5/tests/test14.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test14.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test14.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test14.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test15 [new file with mode: 0755]
libs/libtpl-1.5/tests/test15.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test15.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test15.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test15.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test16 [new file with mode: 0755]
libs/libtpl-1.5/tests/test16.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test16.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test16.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test16.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test17 [new file with mode: 0755]
libs/libtpl-1.5/tests/test17.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test17.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test17.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test17.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test18 [new file with mode: 0755]
libs/libtpl-1.5/tests/test18.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test18.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test18.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test19 [new file with mode: 0755]
libs/libtpl-1.5/tests/test19.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test19.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test19.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test2 [new file with mode: 0755]
libs/libtpl-1.5/tests/test2.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test2.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test2.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test20 [new file with mode: 0755]
libs/libtpl-1.5/tests/test20.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test20.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test20.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test21 [new file with mode: 0755]
libs/libtpl-1.5/tests/test21.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test21.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test21.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test22 [new file with mode: 0755]
libs/libtpl-1.5/tests/test22.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test22.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test22.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test23 [new file with mode: 0755]
libs/libtpl-1.5/tests/test23.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test23.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test23.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test24 [new file with mode: 0755]
libs/libtpl-1.5/tests/test24.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test24.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test24.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test24.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test25 [new file with mode: 0755]
libs/libtpl-1.5/tests/test25.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test25.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test25.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test25.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test26 [new file with mode: 0755]
libs/libtpl-1.5/tests/test26.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test26.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test26.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test26_0.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test26_1.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test26_2.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test26_3.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test27 [new file with mode: 0755]
libs/libtpl-1.5/tests/test27.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test27.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test27.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test28 [new file with mode: 0755]
libs/libtpl-1.5/tests/test28.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test28.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test28.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test29 [new file with mode: 0755]
libs/libtpl-1.5/tests/test29.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test29.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test29.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test3 [new file with mode: 0755]
libs/libtpl-1.5/tests/test3.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test3.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test3.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test30 [new file with mode: 0755]
libs/libtpl-1.5/tests/test30.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test30.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test30.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test31 [new file with mode: 0755]
libs/libtpl-1.5/tests/test31.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test31.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test31.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test32 [new file with mode: 0755]
libs/libtpl-1.5/tests/test32.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test32.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test32.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test33 [new file with mode: 0755]
libs/libtpl-1.5/tests/test33.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test33.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test33.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test34 [new file with mode: 0755]
libs/libtpl-1.5/tests/test34.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test34.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test34.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test35 [new file with mode: 0755]
libs/libtpl-1.5/tests/test35.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test35.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test35.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test36 [new file with mode: 0755]
libs/libtpl-1.5/tests/test36.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test36.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test36.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test37 [new file with mode: 0755]
libs/libtpl-1.5/tests/test37.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test37.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test37.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test38 [new file with mode: 0755]
libs/libtpl-1.5/tests/test38.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test38.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test38.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test39 [new file with mode: 0755]
libs/libtpl-1.5/tests/test39.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test39.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test39.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test39.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test4 [new file with mode: 0755]
libs/libtpl-1.5/tests/test4.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test4.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test4.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test40 [new file with mode: 0755]
libs/libtpl-1.5/tests/test40.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test40.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test40.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test41 [new file with mode: 0755]
libs/libtpl-1.5/tests/test41.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test41.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test41.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test42 [new file with mode: 0755]
libs/libtpl-1.5/tests/test42.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test42.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test42.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test43 [new file with mode: 0755]
libs/libtpl-1.5/tests/test43.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test43.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test43.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test44 [new file with mode: 0755]
libs/libtpl-1.5/tests/test44.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test44.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test44.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test45 [new file with mode: 0755]
libs/libtpl-1.5/tests/test45.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test45.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test45.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test46 [new file with mode: 0755]
libs/libtpl-1.5/tests/test46.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test46.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test46.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test47 [new file with mode: 0755]
libs/libtpl-1.5/tests/test47.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test47.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test47.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test48 [new file with mode: 0755]
libs/libtpl-1.5/tests/test48.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test48.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test48.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test49 [new file with mode: 0755]
libs/libtpl-1.5/tests/test49.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test49.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test49.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test5 [new file with mode: 0755]
libs/libtpl-1.5/tests/test5.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test5.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test5.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test50 [new file with mode: 0755]
libs/libtpl-1.5/tests/test50.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test50.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test50.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test51 [new file with mode: 0755]
libs/libtpl-1.5/tests/test51.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test51.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test51.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test51_0.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test51_1.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test51_2.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test51_3.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test51_4.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test52 [new file with mode: 0755]
libs/libtpl-1.5/tests/test52.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test52.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test52.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test53 [new file with mode: 0755]
libs/libtpl-1.5/tests/test53.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test53.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test53.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test54 [new file with mode: 0755]
libs/libtpl-1.5/tests/test54.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test54.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test54.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test54_0.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test54_1.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test54_2.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test54_3.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test54_4.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test55 [new file with mode: 0755]
libs/libtpl-1.5/tests/test55.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test55.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test55.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test55_0.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test55_1.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test55_2.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test55_3.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test56 [new file with mode: 0755]
libs/libtpl-1.5/tests/test56.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test56.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test56.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test57 [new file with mode: 0755]
libs/libtpl-1.5/tests/test57.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test57.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test57.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test58 [new file with mode: 0755]
libs/libtpl-1.5/tests/test58.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test58.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test58.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test59 [new file with mode: 0755]
libs/libtpl-1.5/tests/test59.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test59.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test59.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test6 [new file with mode: 0755]
libs/libtpl-1.5/tests/test6.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test6.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test6.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test60 [new file with mode: 0755]
libs/libtpl-1.5/tests/test60.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test60.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test60.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test61 [new file with mode: 0755]
libs/libtpl-1.5/tests/test61.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test61.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test61.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test61_0.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test61_1.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test62 [new file with mode: 0755]
libs/libtpl-1.5/tests/test62.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test62.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test62.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test62_0.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test63 [new file with mode: 0755]
libs/libtpl-1.5/tests/test63.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test63.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test63.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test64 [new file with mode: 0755]
libs/libtpl-1.5/tests/test64.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test64.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test64.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test65 [new file with mode: 0755]
libs/libtpl-1.5/tests/test65.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test65.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test65.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test66 [new file with mode: 0755]
libs/libtpl-1.5/tests/test66.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test66.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test66.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test67 [new file with mode: 0755]
libs/libtpl-1.5/tests/test67.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test67.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test67.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test68 [new file with mode: 0755]
libs/libtpl-1.5/tests/test68.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test68.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test68.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test69 [new file with mode: 0755]
libs/libtpl-1.5/tests/test69.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test69.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test69.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test7 [new file with mode: 0755]
libs/libtpl-1.5/tests/test7.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test7.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test7.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test70 [new file with mode: 0755]
libs/libtpl-1.5/tests/test70.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test70.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test70.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test71 [new file with mode: 0755]
libs/libtpl-1.5/tests/test71.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test71.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test71.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test72 [new file with mode: 0755]
libs/libtpl-1.5/tests/test72.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test72.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test72.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test73 [new file with mode: 0755]
libs/libtpl-1.5/tests/test73.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test73.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test73.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test74 [new file with mode: 0755]
libs/libtpl-1.5/tests/test74.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test74.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test74.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test75 [new file with mode: 0755]
libs/libtpl-1.5/tests/test75.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test75.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test75.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test76 [new file with mode: 0755]
libs/libtpl-1.5/tests/test76.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test76.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test76.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test77 [new file with mode: 0755]
libs/libtpl-1.5/tests/test77.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test77.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test77.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test78 [new file with mode: 0755]
libs/libtpl-1.5/tests/test78.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test78.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test78.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test79 [new file with mode: 0755]
libs/libtpl-1.5/tests/test79.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test79.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test79.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test8 [new file with mode: 0755]
libs/libtpl-1.5/tests/test8.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test8.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test8.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test80 [new file with mode: 0755]
libs/libtpl-1.5/tests/test80.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test80.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test80.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test81 [new file with mode: 0755]
libs/libtpl-1.5/tests/test81.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test81.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test81.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test82 [new file with mode: 0755]
libs/libtpl-1.5/tests/test82.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test82.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test82.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test83 [new file with mode: 0755]
libs/libtpl-1.5/tests/test83.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test83.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test83.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test84 [new file with mode: 0755]
libs/libtpl-1.5/tests/test84.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test84.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test84.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test84_0.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test84_1.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test85 [new file with mode: 0755]
libs/libtpl-1.5/tests/test85.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test85.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test85.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test85.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test86 [new file with mode: 0755]
libs/libtpl-1.5/tests/test86.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test86.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test86.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test87 [new file with mode: 0755]
libs/libtpl-1.5/tests/test87.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test87.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test87.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test88 [new file with mode: 0755]
libs/libtpl-1.5/tests/test88.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test88.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test88.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test89 [new file with mode: 0755]
libs/libtpl-1.5/tests/test89.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test89.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test89.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test9 [new file with mode: 0755]
libs/libtpl-1.5/tests/test9.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test9.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test9.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test9.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/test90 [new file with mode: 0755]
libs/libtpl-1.5/tests/test90.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test90.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test90.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test91 [new file with mode: 0755]
libs/libtpl-1.5/tests/test91.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test91.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test91.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test92 [new file with mode: 0755]
libs/libtpl-1.5/tests/test92.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test92.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test92.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test93 [new file with mode: 0755]
libs/libtpl-1.5/tests/test93.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test93.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test93.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test94 [new file with mode: 0755]
libs/libtpl-1.5/tests/test94.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test94.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test94.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test95 [new file with mode: 0755]
libs/libtpl-1.5/tests/test95.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test95.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test95.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test96 [new file with mode: 0755]
libs/libtpl-1.5/tests/test96.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test96.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test96.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test97 [new file with mode: 0755]
libs/libtpl-1.5/tests/test97.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test97.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test97.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test98 [new file with mode: 0755]
libs/libtpl-1.5/tests/test98.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test98.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test98.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test99 [new file with mode: 0755]
libs/libtpl-1.5/tests/test99.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/test99.c [new file with mode: 0755]
libs/libtpl-1.5/tests/test99.out [new file with mode: 0644]
libs/libtpl-1.5/tests/test99.tpl [new file with mode: 0755]
libs/libtpl-1.5/tests/threads/Makefile [new file with mode: 0755]
libs/libtpl-1.5/tests/threads/README [new file with mode: 0755]
libs/libtpl-1.5/tests/threads/test1.ans [new file with mode: 0755]
libs/libtpl-1.5/tests/threads/test1.c [new file with mode: 0755]
w32/Library/FreeSwitchCore.2008.vcproj
w32/Library/FreeSwitchCore.vcproj

index 8c61da454afd445399e87825b4541ad6ea55706c..e7f1f799a57fc263d1f1c24fcdd85ab5a77bcf6f 100644 (file)
@@ -103,6 +103,7 @@ $(RECURSIVE_TARGETS): freeswitch
 
 CORE_CFLAGS  = `$(switch_builddir)/libs/apr/apr-1-config --cflags --cppflags --includes`
 CORE_CFLAGS += `$(switch_builddir)/libs/apr-util/apu-1-config --includes`
+CORE_CFLAGS += -I$(switch_srcdir)/libs/libtpl-1.5/src
 CORE_CFLAGS += -I$(switch_srcdir)/libs/stfu
 CORE_CFLAGS += -I$(switch_builddir)/libs/sqlite
 CORE_CFLAGS += -I$(switch_srcdir)/libs/pcre
@@ -204,6 +205,7 @@ library_include_HEADERS = \
        libs/libteletone/src/libteletone_detect.h \
        libs/libteletone/src/libteletone_generate.h \
        libs/libteletone/src/libteletone.h \
+       libs/libtpl-1.5/src/tpl.h \
        src/include/switch_limit.h \
        src/include/switch_odbc.h
 
@@ -266,6 +268,7 @@ libfreeswitch_la_SOURCES = \
        src/switch_profile.c \
        src/switch_json.c \
        src/switch_curl.c \
+       libs/libtpl-1.5/src/tpl.c \
        libs/stfu/stfu.c \
        libs/libteletone/src/libteletone_detect.c \
        libs/libteletone/src/libteletone_generate.c \
diff --git a/libs/libtpl-1.5/LICENSE b/libs/libtpl-1.5/LICENSE
new file mode 100755 (executable)
index 0000000..7d020b9
--- /dev/null
@@ -0,0 +1,21 @@
+Copyright (c) 2005-2010, Troy Hanson    http://tpl.sourceforge.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:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+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/libs/libtpl-1.5/Makefile.am b/libs/libtpl-1.5/Makefile.am
new file mode 100755 (executable)
index 0000000..780f7ff
--- /dev/null
@@ -0,0 +1,2 @@
+SUBDIRS = src 
+EXTRA_DIST = LICENSE tests lang doc 
diff --git a/libs/libtpl-1.5/Makefile.in b/libs/libtpl-1.5/Makefile.in
new file mode 100644 (file)
index 0000000..89ed294
--- /dev/null
@@ -0,0 +1,635 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  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.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in $(top_srcdir)/config/config.h.in \
+       $(top_srcdir)/configure config/config.guess config/config.sub \
+       config/depcomp config/install-sh config/ltmain.sh \
+       config/missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+       html-recursive info-recursive install-data-recursive \
+       install-dvi-recursive install-exec-recursive \
+       install-html-recursive install-info-recursive \
+       install-pdf-recursive install-ps-recursive install-recursive \
+       installcheck-recursive installdirs-recursive pdf-recursive \
+       ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src 
+EXTRA_DIST = LICENSE tests lang doc 
+all: all-recursive
+
+.SUFFIXES:
+am--refresh:
+       @:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+             cd $(srcdir) && $(AUTOMAKE) --foreign  \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           echo ' $(SHELL) ./config.status'; \
+           $(SHELL) ./config.status;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config/config.h: config/stamp-h1
+       @if test ! -f $@; then \
+         rm -f config/stamp-h1; \
+         $(MAKE) $(AM_MAKEFLAGS) config/stamp-h1; \
+       else :; fi
+
+config/stamp-h1: $(top_srcdir)/config/config.h.in $(top_builddir)/config.status
+       @rm -f config/stamp-h1
+       cd $(top_builddir) && $(SHELL) ./config.status config/config.h
+$(top_srcdir)/config/config.h.in:  $(am__configure_deps) 
+       cd $(top_srcdir) && $(AUTOHEADER)
+       rm -f config/stamp-h1
+       touch $@
+
+distclean-hdr:
+       -rm -f config/config.h config/stamp-h1
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool config.lt
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+       @failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+ctags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       $(am__remove_distdir)
+       test -d $(distdir) || mkdir $(distdir)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -d "$(distdir)/$$subdir" \
+           || $(MKDIR_P) "$(distdir)/$$subdir" \
+           || exit 1; \
+           distdir=`$(am__cd) $(distdir) && pwd`; \
+           top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+           (cd $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$top_distdir" \
+               distdir="$$distdir/$$subdir" \
+               am__remove_distdir=: \
+               am__skip_length_check=: \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+       -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r $(distdir)
+dist-gzip: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+dist-bzip2: distdir
+       tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+       $(am__remove_distdir)
+
+dist-lzma: distdir
+       tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+       $(am__remove_distdir)
+
+dist-tarZ: distdir
+       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+       $(am__remove_distdir)
+
+dist-shar: distdir
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       $(am__remove_distdir)
+
+dist-zip: distdir
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__remove_distdir)
+
+dist dist-all: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       case '$(DIST_ARCHIVES)' in \
+       *.tar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+       *.tar.bz2*) \
+         bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+       *.tar.lzma*) \
+         unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+       *.tar.Z*) \
+         uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+       *.shar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+       *.zip*) \
+         unzip $(distdir).zip ;;\
+       esac
+       chmod -R a-w $(distdir); chmod a+w $(distdir)
+       mkdir $(distdir)/_build
+       mkdir $(distdir)/_inst
+       chmod a-w $(distdir)
+       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+         && cd $(distdir)/_build \
+         && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+           $(DISTCHECK_CONFIGURE_FLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+               distuninstallcheck \
+         && chmod -R a-w "$$dc_install_base" \
+         && ({ \
+              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+             } || { rm -rf "$$dc_destdir"; exit 1; }) \
+         && rm -rf "$$dc_destdir" \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && rm -rf $(DIST_ARCHIVES) \
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+       $(am__remove_distdir)
+       @(echo "$(distdir) archives ready for distribution: "; \
+         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+         sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+       @cd $(distuninstallcheck_dir) \
+       && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+          || { echo "ERROR: files left after uninstall:" ; \
+               if test -n "$(DESTDIR)"; then \
+                 echo "  (check DESTDIR support)"; \
+               fi ; \
+               $(distuninstallcheck_listfiles) ; \
+               exit 1; } >&2
+distcleancheck: distclean
+       @if test '$(srcdir)' = . ; then \
+         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+         exit 1 ; \
+       fi
+       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+         || { echo "ERROR: files left in build directory after distclean:" ; \
+              $(distcleancheck_listfiles) ; \
+              exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+       distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(top_srcdir)/autom4te.cache
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+       install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+       all all-am am--refresh check check-am clean clean-generic \
+       clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \
+       dist-gzip dist-lzma dist-shar dist-tarZ dist-zip distcheck \
+       distclean distclean-generic distclean-hdr distclean-libtool \
+       distclean-tags distcleancheck distdir distuninstallcheck dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-data install-data-am install-dvi install-dvi-am \
+       install-exec install-exec-am install-html install-html-am \
+       install-info install-info-am install-man install-pdf \
+       install-pdf-am install-ps install-ps-am install-strip \
+       installcheck installcheck-am installdirs installdirs-am \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags tags-recursive uninstall uninstall-am
+
+# 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/libs/libtpl-1.5/README b/libs/libtpl-1.5/README
new file mode 100755 (executable)
index 0000000..aefeea2
--- /dev/null
@@ -0,0 +1,56 @@
+tpl: fast, easy serialization in C
+==============================================================================
+
+Documentation for tpl is available in the doc/ directory or at:
+
+    http://tpl.sourceforge.net
+
+You can build tpl as a library, like so:
+
+    ./configure
+    make
+    make install
+
+This installs libtpl.so and libtpl.a into a standard system library directory.
+You can customize the install directory using configure's "--prefix" option:
+
+    ./configure --prefix=/some/directory
+
+For other options accepted by configure, run "./configure --help".
+
+NON-LIBRARY OPTION
+------------------
+Alternatively, if you don't want to muck around with libraries, you can simply        
+copy these two files into your own C project and build them with your program:
+
+    src/tpl.h
+    src/tpl.c
+
+WINDOWS
+-------
+You can build tpl as a DLL under Visual Studio 2008. Or you can use MinGW or
+Cygwin.
+
+SELF-TEST SUITE
+---------------
+The automated self-test can be run by doing:
+
+    cd tests
+    make
+
+LICENSE
+-------
+The BSD license applies to this software. The text is in the LICENSE file.
+
+CREDITS
+-------
+Many people have contributed to tpl, both bits of code and ideas. Rather than
+listing them all here, at risk of omitting anyone- I just wish to say thank
+you. Some particular features are noted with contributors' names in the
+ChangeLog. 
+
+Feel free to send me questions, comments or bug reports.
+
+Troy D. Hanson, February 5, 2010 
+thanson@users.sourceforge.net
+
diff --git a/libs/libtpl-1.5/bootstrap b/libs/libtpl-1.5/bootstrap
new file mode 100755 (executable)
index 0000000..d717c2b
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# THIS SCRIPT IS FOR PROJECT MAINTAINER ONLY
+# It is executed only to generate "configure"
+
+set -x
+aclocal -I config
+autoheader
+libtoolize --copy --force
+automake --foreign --add-missing --copy
+autoconf
diff --git a/libs/libtpl-1.5/configure.ac b/libs/libtpl-1.5/configure.ac
new file mode 100755 (executable)
index 0000000..3d2fe0e
--- /dev/null
@@ -0,0 +1,28 @@
+AC_PREREQ(2.59)
+
+AC_INIT([libtpl], [1.4], [thanson@users.sourceforge.net])
+AC_CONFIG_SRCDIR(src/tpl.c)
+AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_HEADERS(config/config.h)
+AM_INIT_AUTOMAKE
+AC_PROG_CC
+dnl next 4 lines are a hack to avoid libtool's
+dnl needless checks for C++ and Fortran compilers
+m4_undefine([AC_PROG_CXX])
+m4_defun([AC_PROG_CXX],[])
+m4_undefine([AC_PROG_F77])
+m4_defun([AC_PROG_F77],[])
+AC_PROG_LIBTOOL
+
+dnl detect Cygwin or MinGW and use mmap family replacements
+AC_CONFIG_LIBOBJ_DIR(src/win)
+case $host in
+     *-*-mingw32* | *-*-cygwin* | *-*-windows*)
+     AC_LIBOBJ(mmap)
+     AC_MSG_NOTICE([using custom mmap for Cygwin/MinGW])
+     ;;
+esac
+
+AC_CONFIG_FILES(src/win/Makefile src/Makefile Makefile)
+AC_OUTPUT
+
diff --git a/libs/libtpl-1.5/doc/Makefile b/libs/libtpl-1.5/doc/Makefile
new file mode 100755 (executable)
index 0000000..eaa3d49
--- /dev/null
@@ -0,0 +1,26 @@
+all: css userguide pdf changelog perl 
+
+userguide:     txt/userguide.txt
+       asciidoc --unsafe --out-file=html/userguide.html -a linkcss=1 -a theme=tdh txt/userguide.txt 
+
+changelog:     txt/ChangeLog.txt
+       asciidoc --out-file=html/ChangeLog.html txt/ChangeLog.txt 
+
+.PHONY: pdf
+
+pdf: txt/userguide.txt
+       a2x -f pdf $<
+       mv txt/userguide.pdf pdf/
+       cd html && ln -sf ../pdf/userguide.pdf userguide.pdf
+       rm txt/userguide.xml
+
+perl: txt/perl.txt
+       asciidoc --unsafe --out-file=html/perl.html -a linkcss=1 -a theme=tdh txt/perl.txt 
+
+css: html/toc.css
+       cat /etc/asciidoc/stylesheets/xhtml11.css html/toc.css > html/tdh.css
+       cp /etc/asciidoc/stylesheets/xhtml11-quirks.css html/tdh-quirks.css 
+
+docbook: txt/userguide.txt
+       asciidoc -b docbook --out-file=/tmp/userguide.xml txt/userguide.txt 
+       xmlto -o html html-nochunks /tmp/userguide.xml 
diff --git a/libs/libtpl-1.5/doc/NOTES b/libs/libtpl-1.5/doc/NOTES
new file mode 100755 (executable)
index 0000000..9133089
--- /dev/null
@@ -0,0 +1,11 @@
+# maintainer notes
+
+# IE6 png gamma bug:
+# PNG images in IE6 display with wrong background colors,
+# solution: save PNG in Gimp *Without save gamma checked*
+
+#update sourceforge web site:
+#cd html
+#scp *.{html,css} thanson@shell.sourceforge.net:/home/groups/t/tp/tpl/htdocs
+#cd img
+#scp *.png *.jpg thanson@shell.sourceforge.net:/home/groups/t/tp/tpl/htdocs/img
diff --git a/libs/libtpl-1.5/doc/html/ChangeLog.html b/libs/libtpl-1.5/doc/html/ChangeLog.html
new file mode 100755 (executable)
index 0000000..a051e60
--- /dev/null
@@ -0,0 +1,602 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.5.0" />\r
+<title>tpl ChangeLog</title>\r
+<style type="text/css">\r
+/* Debug borders */\r
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {\r
+/*\r
+  border: 1px solid red;\r
+*/\r
+}\r
+\r
+body {\r
+  margin: 1em 5% 1em 5%;\r
+}\r
+\r
+a {\r
+  color: blue;\r
+  text-decoration: underline;\r
+}\r
+a:visited {\r
+  color: fuchsia;\r
+}\r
+\r
+em {\r
+  font-style: italic;\r
+  color: navy;\r
+}\r
+\r
+strong {\r
+  font-weight: bold;\r
+  color: #083194;\r
+}\r
+\r
+tt {\r
+  color: navy;\r
+}\r
+\r
+h1, h2, h3, h4, h5, h6 {\r
+  color: #527bbd;\r
+  font-family: sans-serif;\r
+  margin-top: 1.2em;\r
+  margin-bottom: 0.5em;\r
+  line-height: 1.3;\r
+}\r
+\r
+h1, h2, h3 {\r
+  border-bottom: 2px solid silver;\r
+}\r
+h2 {\r
+  padding-top: 0.5em;\r
+}\r
+h3 {\r
+  float: left;\r
+}\r
+h3 + * {\r
+  clear: left;\r
+}\r
+\r
+div.sectionbody {\r
+  font-family: serif;\r
+  margin-left: 0;\r
+}\r
+\r
+hr {\r
+  border: 1px solid silver;\r
+}\r
+\r
+p {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0.5em;\r
+}\r
+\r
+ul, ol, li > p {\r
+  margin-top: 0;\r
+}\r
+\r
+pre {\r
+  padding: 0;\r
+  margin: 0;\r
+}\r
+\r
+span#author {\r
+  color: #527bbd;\r
+  font-family: sans-serif;\r
+  font-weight: bold;\r
+  font-size: 1.1em;\r
+}\r
+span#email {\r
+}\r
+span#revnumber, span#revdate, span#revremark {\r
+  font-family: sans-serif;\r
+}\r
+\r
+div#footer {\r
+  font-family: sans-serif;\r
+  font-size: small;\r
+  border-top: 2px solid silver;\r
+  padding-top: 0.5em;\r
+  margin-top: 4.0em;\r
+}\r
+div#footer-text {\r
+  float: left;\r
+  padding-bottom: 0.5em;\r
+}\r
+div#footer-badges {\r
+  float: right;\r
+  padding-bottom: 0.5em;\r
+}\r
+\r
+div#preamble {\r
+  margin-top: 1.5em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,\r
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,\r
+div.admonitionblock {\r
+  margin-top: 0.25em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.admonitionblock {\r
+  margin-top: 2.5em;\r
+  margin-bottom: 2.5em;\r
+}\r
+\r
+div.content { /* Block element content. */\r
+  padding: 0;\r
+}\r
+\r
+/* Block element titles. */\r
+div.title, caption.title {\r
+  color: #527bbd;\r
+  font-family: sans-serif;\r
+  font-weight: bold;\r
+  text-align: left;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.5em;\r
+}\r
+div.title + * {\r
+  margin-top: 0;\r
+}\r
+\r
+td div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content + div.title {\r
+  margin-top: 0.0em;\r
+}\r
+\r
+div.sidebarblock > div.content {\r
+  background: #ffffee;\r
+  border: 1px solid silver;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.listingblock > div.content {\r
+  border: 1px solid silver;\r
+  background: #f4f4f4;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.quoteblock {\r
+  padding-left: 2.0em;\r
+  margin-right: 10%;\r
+}\r
+div.quoteblock > div.attribution {\r
+  padding-top: 0.5em;\r
+  text-align: right;\r
+}\r
+\r
+div.verseblock {\r
+  padding-left: 2.0em;\r
+  margin-right: 10%;\r
+}\r
+div.verseblock > div.content {\r
+  white-space: pre;\r
+}\r
+div.verseblock > div.attribution {\r
+  padding-top: 0.75em;\r
+  text-align: left;\r
+}\r
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */\r
+div.verseblock + div.attribution {\r
+  text-align: left;\r
+}\r
+\r
+div.admonitionblock .icon {\r
+  vertical-align: top;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  text-decoration: underline;\r
+  color: #527bbd;\r
+  padding-right: 0.5em;\r
+}\r
+div.admonitionblock td.content {\r
+  padding-left: 0.5em;\r
+  border-left: 2px solid silver;\r
+}\r
+\r
+div.exampleblock > div.content {\r
+  border-left: 2px solid silver;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.imageblock div.content { padding-left: 0; }\r
+span.image img { border-style: none; }\r
+a.image:visited { color: white; }\r
+\r
+dl {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+dt {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0;\r
+  font-style: normal;\r
+  color: navy;\r
+}\r
+dd > *:first-child {\r
+  margin-top: 0.1em;\r
+}\r
+\r
+ul, ol {\r
+    list-style-position: outside;\r
+}\r
+ol.arabic {\r
+  list-style-type: decimal;\r
+}\r
+ol.loweralpha {\r
+  list-style-type: lower-alpha;\r
+}\r
+ol.upperalpha {\r
+  list-style-type: upper-alpha;\r
+}\r
+ol.lowerroman {\r
+  list-style-type: lower-roman;\r
+}\r
+ol.upperroman {\r
+  list-style-type: upper-roman;\r
+}\r
+\r
+div.compact ul, div.compact ol,\r
+div.compact p, div.compact p,\r
+div.compact div, div.compact div {\r
+  margin-top: 0.1em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+div.tableblock > table {\r
+  border: 3px solid #527bbd;\r
+}\r
+thead {\r
+  font-family: sans-serif;\r
+  font-weight: bold;\r
+}\r
+tfoot {\r
+  font-weight: bold;\r
+}\r
+td > div.verse {\r
+  white-space: pre;\r
+}\r
+p.table {\r
+  margin-top: 0;\r
+}\r
+/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+div.tableblock > table[frame="void"] {\r
+  border-style: none;\r
+}\r
+div.tableblock > table[frame="hsides"] {\r
+  border-left-style: none;\r
+  border-right-style: none;\r
+}\r
+div.tableblock > table[frame="vsides"] {\r
+  border-top-style: none;\r
+  border-bottom-style: none;\r
+}\r
+\r
+\r
+div.hdlist {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+div.hdlist tr {\r
+  padding-bottom: 15px;\r
+}\r
+dt.hdlist1.strong, td.hdlist1.strong {\r
+  font-weight: bold;\r
+}\r
+td.hdlist1 {\r
+  vertical-align: top;\r
+  font-style: normal;\r
+  padding-right: 0.8em;\r
+  color: navy;\r
+}\r
+td.hdlist2 {\r
+  vertical-align: top;\r
+}\r
+div.hdlist.compact tr {\r
+  margin: 0;\r
+  padding-bottom: 0;\r
+}\r
+\r
+.comment {\r
+  background: yellow;\r
+}\r
+\r
+@media print {\r
+  div#footer-badges { display: none; }\r
+}\r
+\r
+div#toctitle {\r
+  color: #527bbd;\r
+  font-family: sans-serif;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {\r
+  margin-top: 0;\r
+  margin-bottom: 0;\r
+}\r
+div.toclevel2 {\r
+  margin-left: 2em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel3 {\r
+  margin-left: 4em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel4 {\r
+  margin-left: 6em;\r
+  font-size: 0.9em;\r
+}\r
+/* Workarounds for IE6's broken and incomplete CSS2. */\r
+\r
+div.sidebar-content {\r
+  background: #ffffee;\r
+  border: 1px solid silver;\r
+  padding: 0.5em;\r
+}\r
+div.sidebar-title, div.image-title {\r
+  color: #527bbd;\r
+  font-family: sans-serif;\r
+  font-weight: bold;\r
+  margin-top: 0.0em;\r
+  margin-bottom: 0.5em;\r
+}\r
+\r
+div.listingblock div.content {\r
+  border: 1px solid silver;\r
+  background: #f4f4f4;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.quoteblock-attribution {\r
+  padding-top: 0.5em;\r
+  text-align: right;\r
+}\r
+\r
+div.verseblock-content {\r
+  white-space: pre;\r
+}\r
+div.verseblock-attribution {\r
+  padding-top: 0.75em;\r
+  text-align: left;\r
+}\r
+\r
+div.exampleblock-content {\r
+  border-left: 2px solid silver;\r
+  padding-left: 0.5em;\r
+}\r
+\r
+/* IE6 sets dynamically generated links as visited. */\r
+div#toc a:visited { color: blue; }\r
+</style>\r
+</head>\r
+<body>\r
+<div id="header">\r
+<h1>tpl ChangeLog</h1>\r
+</div>\r
+<h2 id="_version_1_5_2010_02_05">Version 1.5 (2010-02-05)</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+tpl now builds as a DLL under Microsoft Visual Studio! (thanks, degski and Zhang Yafei!)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+there are now two download options: the <a href="http://downloads.sourceforge.net/tpl/libtpl-1.5.tar.bz2">tarball</a> and the Visual Studio <a href="http://downloads.sourceforge.net/tpl/tpl-1.5-vs2008.zip">solution</a>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+a crash in <tt>tpl_free</tt> on certain format strings has been fixed (thanks, Eric Rose!)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+fixed a bug in <tt>tpl_dump</tt> on 64-bit, big-endian platforms\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+changed some pointer casts from <tt>long</tt> to <tt>uintptr_t</tt> since 64-bit Windows has 32-bit longs\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+tpl has been downloaded 4,195 times.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+<h2 id="_version_1_4_2009_04_21">Version 1.4 (2009-04-21)</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+fixed-length arrays can now be multi-dimensional like <tt>i##</tt>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+fixed-length string arrays like <tt>s#</tt> are now supported\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+nested structures can now be expressed, using the dollar symbol, e.g. <tt>S(ci$(cc))</tt>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>tpl_dump</tt> can use a caller-allocated output buffer (<tt>TPL_MEM|TPL_PREALLOCD</tt>)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>tpl_load</tt> can tolerate excess space in input buffer (<tt>TPL_MEM|TPL_EXCESS_OK</tt>)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+implement <tt>TPL_FXLENS</tt> flag for <tt>tpl_peek</tt> to get lengths of fixed-length arrays\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+implement <tt>TPL_GETSIZE</tt> flag for <tt>tpl_dump</tt> to get dump size without dumping\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+fix success return code from <tt>tpl_dump(TPL_FD,...)</tt> (thanks, Max Lapan!)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+deprecated the wildcard unpacking <tt>S(*)</tt> feature\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+<h2 id="_version_1_3_2009_02_10">Version 1.3 (2009-02-10)</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+added <tt>TPL_DATAPEEK</tt> mode for <tt>tpl_peek</tt>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added support for <tt>NULL</tt> strings\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added support for 16-bit integer types (<tt>j</tt>,<tt>v</tt>)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added <tt>tpl_jot</tt>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added support for fixed-length arrays of structures <tt>S(...)#</tt>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added support for pre-C99 compilers (thanks, Wei Wei!)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+improved structure alignment calculation (thanks, Wu Yongwei!)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added RPM spec file (thanks, Alessandro Ren!)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+compiles cleanly with <tt>-Wall</tt> and <tt>-pedantic</tt> and with <tt>-O3</tt>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+made <a href="license.html">BSD license</a> terms even more permissive\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+test suite: exit with status zero when all tests pass\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added PDF user guide\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added <a href="http://troydhanson.wordpress.com/feed/">update news</a> <span class="image">\r
+<img src="img/rss.png" alt="(RSS)" />\r
+</span>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+added <a href="http://apps.sourceforge.net/mediawiki/tpl/">tpl wiki</a>\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+<h2 id="_version_1_2_2007_04_27">Version 1.2 (2007-04-27)</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Perl API and XML converter support 64-bit types\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+<h2 id="_version_1_1_2007_04_25">Version 1.1 (2007-04-25)</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+support for serializing C structures\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+support for serializing fixed-length arrays\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+MinGW support (thanks, Horea Haitonic!)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+revised User Guide\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+<h2 id="_version_1_0_2006_09_28">Version 1.0 (2006-09-28)</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Initial version\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated 2010-02-05 19:31:37 PDT\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/libs/libtpl-1.5/doc/html/img/banner.png b/libs/libtpl-1.5/doc/html/img/banner.png
new file mode 100755 (executable)
index 0000000..ba9ffe8
Binary files /dev/null and b/libs/libtpl-1.5/doc/html/img/banner.png differ
diff --git a/libs/libtpl-1.5/doc/html/img/banner.svg b/libs/libtpl-1.5/doc/html/img/banner.svg
new file mode 100755 (executable)
index 0000000..f9f1f85
--- /dev/null
@@ -0,0 +1,429 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="728px"
+   height="90px"
+   id="svg1323"
+   sodipodi:version="0.32"
+   inkscape:version="0.44"
+   sodipodi:docbase="/home/thanson/code/tpl/trunk/doc/html/img"
+   sodipodi:docname="banner.svg"
+   inkscape:export-filename="/home/thanson/code/tpl/trunk/doc/html/img/banner.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs1325">
+    <linearGradient
+       id="linearGradient22211">
+      <stop
+         style="stop-color:#2e7ce0;stop-opacity:0;"
+         offset="0"
+         id="stop22237" />
+      <stop
+         id="stop22215"
+         offset="1"
+         style="stop-color:#2e7ce0;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient20106">
+      <stop
+         style="stop-color:#f0f3f7;stop-opacity:1;"
+         offset="0"
+         id="stop20108" />
+      <stop
+         style="stop-color:#f0f3f7;stop-opacity:0;"
+         offset="1"
+         id="stop20110" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient19154">
+      <stop
+         style="stop-color:#005fd9;stop-opacity:1;"
+         offset="0"
+         id="stop19156" />
+      <stop
+         style="stop-color:#005fd9;stop-opacity:0;"
+         offset="1"
+         id="stop19158" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient19142">
+      <stop
+         style="stop-color:#4ec2f0;stop-opacity:1;"
+         offset="0"
+         id="stop19144" />
+      <stop
+         style="stop-color:#4ec2f0;stop-opacity:0;"
+         offset="1"
+         id="stop19146" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient19132">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop19134" />
+      <stop
+         id="stop19140"
+         offset="0.5"
+         style="stop-color:#00d1f6;stop-opacity:0.49803922;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop19136" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19142"
+       id="radialGradient19150"
+       cx="651"
+       cy="50"
+       fx="651"
+       fy="50"
+       r="49.5"
+       gradientTransform="matrix(1,0,0,0.616162,1.124101e-15,19.19192)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient19160"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient19224"
+       gradientUnits="userSpaceOnUse"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47"
+       gradientTransform="matrix(5.590915,0,0,1.101015,-3310.4,161.4223)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient20106"
+       id="radialGradient20112"
+       cx="125.1579"
+       cy="213.03658"
+       fx="125.1579"
+       fy="213.03658"
+       r="27.577164"
+       gradientTransform="matrix(1,0,0,0.923077,0,16.38742)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient20176"
+       gradientUnits="userSpaceOnUse"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47"
+       gradientTransform="translate(-38.18377,318.1981)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient20203"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-38.18377,318.1981)"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient20269"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-38.18377,318.1981)"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient20389"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.755096,0,0,1.101015,-1053.937,335.4223)"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient22243"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.867037,0,0,1.101015,-1120.758,425.4223)"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient24137"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.755096,0,0,1.101015,-1052.937,435.4223)"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient19154"
+       id="linearGradient24144"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.755096,0,0,1.101015,-1049.937,270.4223)"
+       x1="588"
+       y1="47"
+       x2="722"
+       y2="47" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="497.48754"
+     inkscape:cy="-4.5816549"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="1176"
+     inkscape:window-height="633"
+     inkscape:window-x="23"
+     inkscape:window-y="48" />
+  <metadata
+     id="metadata1328">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <rect
+       style="fill:#3c85e2;fill-opacity:1;fill-rule:nonzero;stroke:#ffcb53;stroke-width:4.0415926;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect20271"
+       width="240.0993"
+       height="77.071068"
+       x="4.1015167"
+       y="3.6345825"
+       rx="29.60623" />
+    <rect
+       y="46.014687"
+       x="-236.92256"
+       height="16.982321"
+       width="16.982321"
+       id="rect24091"
+       style="fill:#2fa4db;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       transform="scale(-1,1)" />
+    <rect
+       y="46.014687"
+       x="-219.80927"
+       height="16.982321"
+       width="16.982321"
+       id="rect24093"
+       style="fill:#2fa4db;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       transform="scale(-1,1)" />
+    <rect
+       style="fill:#2fa4db;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect24095"
+       width="16.982321"
+       height="16.982321"
+       x="-202.92258"
+       y="46.014687"
+       transform="scale(-1,1)" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#e33019;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path24097"
+       sodipodi:cx="231.91481"
+       sodipodi:cy="-69.739944"
+       sodipodi:rx="3.7148824"
+       sodipodi:ry="3.7148824"
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       transform="translate(-102.0443,123.8305)" />
+    <path
+       transform="translate(-76.04438,87.8305)"
+       sodipodi:type="arc"
+       style="fill:#e38c19;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path24099"
+       sodipodi:cx="231.91481"
+       sodipodi:cy="-69.739944"
+       sodipodi:rx="3.7148824"
+       sodipodi:ry="3.7148824"
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z" />
+    <path
+       transform="translate(-64.0444,105.8305)"
+       sodipodi:type="arc"
+       style="fill:#88dfdb;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path24101"
+       sodipodi:cx="231.91481"
+       sodipodi:cy="-69.739944"
+       sodipodi:rx="3.7148824"
+       sodipodi:ry="3.7148824"
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24103"
+       style="fill:#79c71a;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="translate(-76.04438,123.8305)" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24105"
+       style="fill:#f5e1a2;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="translate(-88.04433,105.8305)" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24107"
+       style="fill:#d8643e;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="matrix(-1,0,0,1,460.1983,124.4007)" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24109"
+       style="fill:#d8643e;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="matrix(-1,0,0,1,442.9488,124.4007)" />
+    <path
+       transform="matrix(-1,0,0,1,426.1983,124.4007)"
+       sodipodi:type="arc"
+       style="fill:#d8643e;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path24111"
+       sodipodi:cx="231.91481"
+       sodipodi:cy="-69.739944"
+       sodipodi:rx="3.7148824"
+       sodipodi:ry="3.7148824"
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 146.68046,40.305464 L 153.06062,49.875694"
+       id="path24113"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 146.68046,31.875694 L 153.06062,22.305464"
+       id="path24115"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;marker-end:none;stroke-opacity:1"
+       d="M 158.68046,22.305464 L 165.06062,31.875694"
+       id="path24117"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 224.06859,54.660809 L 215.24887,54.660809"
+       id="path24119"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 206.81911,54.660809 L 198.49837,54.660809"
+       id="path24121"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 140.5923,40.305464 L 133.14878,49.875694"
+       id="path24123"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 198.08195,67.740894 L 198.08195,67.740894"
+       id="path24125"
+       inkscape:connector-type="polyline" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24127"
+       style="fill:#d8643e;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="matrix(-1,0,0,1,410.1983,124.4007)" />
+    <path
+       inkscape:connector-type="polyline"
+       id="path24129"
+       d="M 190.81911,54.660809 L 182.49837,54.660809"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 170.23387,40.305398 L 175.92003,50.445833"
+       id="path24131"
+       inkscape:connector-type="polyline" />
+    <text
+       xml:space="preserve"
+       style="font-size:57.24448395px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ff8900;fill-opacity:1;stroke:#ffc900;stroke-width:2.58558559px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.95530725;font-family:Bitstream Vera Sans Mono"
+       x="13.482153"
+       y="61.413116"
+       id="text24133"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan24135"
+         x="13.482153"
+         y="61.413116"
+         style="font-size:57.24448395px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ff8900;fill-opacity:1;stroke:#ffc900;stroke-opacity:0.95530725;font-family:Bitstream Vera Sans Mono">tpl</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:33.35416794px;font-style:normal;font-weight:normal;fill:#ff8900;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="313.95825"
+       y="31.16275"
+       id="text24140"><tspan
+         sodipodi:role="line"
+         id="tspan24142"
+         x="313.95825"
+         y="31.16275"
+         style="stroke:none;stroke-opacity:1">easily store and retrieve </tspan><tspan
+         sodipodi:role="line"
+         x="313.95825"
+         y="72.85546"
+         style="font-weight:bold;stroke:none;stroke-opacity:1"
+         id="tspan1941">binary data in C</tspan><tspan
+         sodipodi:role="line"
+         x="313.95825"
+         y="114.54817"
+         style="stroke:none;stroke-opacity:1"
+         id="tspan1939" /></text>
+  </g>
+</svg>
diff --git a/libs/libtpl-1.5/doc/html/img/grad_azure.png b/libs/libtpl-1.5/doc/html/img/grad_azure.png
new file mode 100755 (executable)
index 0000000..bf5c0cf
Binary files /dev/null and b/libs/libtpl-1.5/doc/html/img/grad_azure.png differ
diff --git a/libs/libtpl-1.5/doc/html/img/grad_azure.svg b/libs/libtpl-1.5/doc/html/img/grad_azure.svg
new file mode 100755 (executable)
index 0000000..ab5fc49
--- /dev/null
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.43"
+   sodipodi:docbase="/home/thanson/code/tpl/doc/html/img"
+   sodipodi:docname="grad_cyan.svg">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient2194">
+      <stop
+         style="stop-color:#1190ed;stop-opacity:1;"
+         offset="0"
+         id="stop2196" />
+      <stop
+         style="stop-color:#f9f9f9;stop-opacity:0;"
+         offset="1"
+         id="stop2198" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2184">
+      <stop
+         style="stop-color:#0000e0;stop-opacity:1;"
+         offset="0"
+         id="stop2186" />
+      <stop
+         style="stop-color:#0000e0;stop-opacity:0;"
+         offset="1"
+         id="stop2188" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2184"
+       id="linearGradient2190"
+       x1="76.642857"
+       y1="679.50504"
+       x2="523.35714"
+       y2="679.50504"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2194"
+       id="linearGradient2200"
+       x1="335.5"
+       y1="654.61218"
+       x2="506"
+       y2="654.61218"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2"
+     inkscape:cx="488.2215"
+     inkscape:cy="372.85714"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="797"
+     inkscape:window-height="575"
+     inkscape:window-x="112"
+     inkscape:window-y="25" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       style="opacity:0.96629214;fill:url(#linearGradient2200);fill-opacity:1.0;stroke:none;stroke-width:4.68499994;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2192"
+       width="170.5"
+       height="9.5"
+       x="335.5"
+       y="649.86218"
+       inkscape:export-filename="/home/thanson/code/tpl/doc/html/img/grad_cyan.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90" />
+  </g>
+</svg>
diff --git a/libs/libtpl-1.5/doc/html/img/rss.png b/libs/libtpl-1.5/doc/html/img/rss.png
new file mode 100755 (executable)
index 0000000..b3c949d
Binary files /dev/null and b/libs/libtpl-1.5/doc/html/img/rss.png differ
diff --git a/libs/libtpl-1.5/doc/html/img/tpl-mini.png b/libs/libtpl-1.5/doc/html/img/tpl-mini.png
new file mode 100755 (executable)
index 0000000..7c193e9
Binary files /dev/null and b/libs/libtpl-1.5/doc/html/img/tpl-mini.png differ
diff --git a/libs/libtpl-1.5/doc/html/img/tpl-mini.svg b/libs/libtpl-1.5/doc/html/img/tpl-mini.svg
new file mode 100755 (executable)
index 0000000..07df268
--- /dev/null
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="105.05521"
+   height="34.90324"
+   id="svg2267"
+   sodipodi:version="0.32"
+   inkscape:version="0.44"
+   version="1.0"
+   sodipodi:docbase="/home/thanson/code/uthash/trunk/doc/html/img"
+   sodipodi:docname="tpl-mini.svg">
+  <defs
+     id="defs3" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="63.027613"
+     inkscape:cy="11.686998"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     width="118.44px"
+     height="22.66px"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="916"
+     inkscape:window-height="626"
+     inkscape:window-x="15"
+     inkscape:window-y="95">
+    <sodipodi:guide
+       orientation="horizontal"
+       position="28.768574"
+       id="guide2299" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata2271">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-69.67658,-43.42744)">
+    <rect
+       style="fill:#3c85e2;fill-opacity:1;fill-rule:nonzero;stroke:#ffcb53;stroke-width:1.73912036;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect20271"
+       width="103.31609"
+       height="33.16412"
+       x="70.546143"
+       y="44.296997"
+       rx="12.739729" />
+    <rect
+       y="62.533398"
+       x="-170.73035"
+       height="7.3075895"
+       width="7.3075895"
+       id="rect24091"
+       style="fill:#2fa4db;fill-opacity:1;stroke:black;stroke-width:0.43030569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       transform="scale(-1,1)" />
+    <rect
+       y="62.533398"
+       x="-163.36638"
+       height="7.3075895"
+       width="7.3075895"
+       id="rect24093"
+       style="fill:#2fa4db;fill-opacity:1;stroke:black;stroke-width:0.43030569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       transform="scale(-1,1)" />
+    <rect
+       style="fill:#2fa4db;fill-opacity:1;stroke:black;stroke-width:0.43030569;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect24095"
+       width="7.3075895"
+       height="7.3075895"
+       x="-156.09996"
+       y="62.533398"
+       transform="scale(-1,1)" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#e33019;fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path24097"
+       sodipodi:cx="231.91481"
+       sodipodi:cy="-69.739944"
+       sodipodi:rx="3.7148824"
+       sodipodi:ry="3.7148824"
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       transform="matrix(0.430306,0,0,0.430306,24.87099,96.01799)" />
+    <path
+       transform="matrix(0.430306,0,0,0.430306,36.05889,80.52698)"
+       sodipodi:type="arc"
+       style="fill:#e38c19;fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path24099"
+       sodipodi:cx="231.91481"
+       sodipodi:cy="-69.739944"
+       sodipodi:rx="3.7148824"
+       sodipodi:ry="3.7148824"
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z" />
+    <path
+       transform="matrix(0.430306,0,0,0.430306,41.22256,88.27247)"
+       sodipodi:type="arc"
+       style="fill:#88dfdb;fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path24101"
+       sodipodi:cx="231.91481"
+       sodipodi:cy="-69.739944"
+       sodipodi:rx="3.7148824"
+       sodipodi:ry="3.7148824"
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24103"
+       style="fill:#79c71a;fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="matrix(0.430306,0,0,0.430306,36.05889,96.01799)" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24105"
+       style="fill:#f5e1a2;fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="matrix(0.430306,0,0,0.430306,30.89524,88.27247)" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24107"
+       style="fill:#d8643e;fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="matrix(-0.430306,0,0,0.430306,266.8073,96.26334)" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24109"
+       style="fill:#d8643e;fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="matrix(-0.430306,0,0,0.430306,259.3847,96.26334)" />
+    <path
+       transform="matrix(-0.430306,0,0,0.430306,252.1769,96.26334)"
+       sodipodi:type="arc"
+       style="fill:#d8643e;fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path24111"
+       sodipodi:cx="231.91481"
+       sodipodi:cy="-69.739944"
+       sodipodi:rx="3.7148824"
+       sodipodi:ry="3.7148824"
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 131.89866,60.076683 L 134.64408,64.194808"
+       id="path24113"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 131.89866,56.449305 L 134.64408,52.33118"
+       id="path24115"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:square;stroke-linejoin:miter;marker-end:none;stroke-opacity:1"
+       d="M 137.06234,52.33118 L 139.80775,56.449305"
+       id="path24117"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 165.19922,66.25387 L 161.40404,66.25387"
+       id="path24119"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 157.77667,66.25387 L 154.19622,66.25387"
+       id="path24121"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 129.2789,60.076683 L 126.07591,64.194808"
+       id="path24123"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 154.01702,71.882304 L 154.01702,71.882304"
+       id="path24125"
+       inkscape:connector-type="polyline" />
+    <path
+       d="M 235.62969 -69.739944 A 3.7148824 3.7148824 0 1 1  228.19993,-69.739944 A 3.7148824 3.7148824 0 1 1  235.62969 -69.739944 z"
+       sodipodi:ry="3.7148824"
+       sodipodi:rx="3.7148824"
+       sodipodi:cy="-69.739944"
+       sodipodi:cx="231.91481"
+       id="path24127"
+       style="fill:#d8643e;fill-opacity:1;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       sodipodi:type="arc"
+       transform="matrix(-0.430306,0,0,0.430306,245.292,96.26334)" />
+    <path
+       inkscape:connector-type="polyline"
+       id="path24129"
+       d="M 150.89178,66.25387 L 147.31131,66.25387"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.43030569px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 142.03383,60.076654 L 144.48062,64.440141"
+       id="path24131"
+       inkscape:connector-type="polyline" />
+    <text
+       xml:space="preserve"
+       style="font-size:24.63262939px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ff8900;fill-opacity:1;stroke:#ffc900;stroke-width:1.11259222px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.95530725;font-family:Bitstream Vera Sans Mono"
+       x="74.58268"
+       y="69.159424"
+       id="text24133"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan24135"
+         x="74.58268"
+         y="69.159424"
+         style="font-size:24.63262939px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ff8900;fill-opacity:1;stroke:#ffc900;stroke-width:1.11259222;stroke-opacity:0.95530725;font-family:Bitstream Vera Sans Mono">tpl</tspan></text>
+  </g>
+</svg>
diff --git a/libs/libtpl-1.5/doc/html/img/tpl.dia b/libs/libtpl-1.5/doc/html/img/tpl.dia
new file mode 100755 (executable)
index 0000000..d63ed77
Binary files /dev/null and b/libs/libtpl-1.5/doc/html/img/tpl.dia differ
diff --git a/libs/libtpl-1.5/doc/html/img/tpl.png b/libs/libtpl-1.5/doc/html/img/tpl.png
new file mode 100755 (executable)
index 0000000..59f775c
Binary files /dev/null and b/libs/libtpl-1.5/doc/html/img/tpl.png differ
diff --git a/libs/libtpl-1.5/doc/html/img/tpl_aai.dia b/libs/libtpl-1.5/doc/html/img/tpl_aai.dia
new file mode 100755 (executable)
index 0000000..464ccbc
Binary files /dev/null and b/libs/libtpl-1.5/doc/html/img/tpl_aai.dia differ
diff --git a/libs/libtpl-1.5/doc/html/index.html b/libs/libtpl-1.5/doc/html/index.html
new file mode 100755 (executable)
index 0000000..ac74a00
--- /dev/null
@@ -0,0 +1,162 @@
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XTHML 1.0 Strict//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <link rel="stylesheet" type="text/css" href="styles.css" />
+    <title>tpl home page</title>
+  </head>
+  <body>
+
+  <div id="banner">
+  <img src="img/banner.png" alt="easy data storage and retrieval in C" />
+  </div> <!-- banner -->
+
+  <div id="topnav">
+  <a href="http://sourceforge.net/projects/tpl/">sf.net summary page</a> &gt;
+  tpl home
+  </div> <!-- topnav -->
+
+  <hr />
+  <div id="mid">
+
+      <div id="nav">
+
+
+        <h2>documentation</h2>
+        <div><a href="userguide.html">user guide</a> (<a href="userguide.html">html</a>, <a href="userguide.pdf">pdf</a>)</div>
+
+        <h2>download</h2>
+        <h3>Linux, Mac OSX, Solaris, BSD</h3>
+        <div><a href="http://downloads.sourceforge.net/tpl/libtpl-1.5.tar.bz2">libtpl-1.5.tar.bz2</a></div>
+        <h3>Visual Studio 2008 Solution</h3>
+        <div><a href="http://downloads.sourceforge.net/tpl/tpl-1.5-vs2008.zip">tpl-1.5-vs2008.zip</a></div>
+
+        <h2>last release</h2>
+        <div>February, 2010</div>
+        <div><a href="ChangeLog.html">ChangeLog</a></div>
+
+        <h2>license</h2>
+        <div><a href="license.html">BSD revised</a></div>
+
+        <h2>news feed</h2>
+        <div><a href="http://troydhanson.wordpress.com/">updates blog</a> (<a href="http://troydhanson.wordpress.com/feed/">rss</a>)<img alt=" rss" src="img/rss.png"/></div>
+
+        <h2>platforms</h2>
+        <div>linux</div>
+        <div>os x</div>
+        <div>windows</div>
+        <div>solaris</div>
+        <div>openbsd</div>
+
+        <h2>other projects</h2>
+        <div><a href="http://uthash.sourceforge.net/">uthash</a></div>
+        <div><a href="http://tkhanson.net/misc/">scripts & snippets</a></div>
+
+        <h2>developer</h2>
+        <div>Troy D. Hanson</div>
+        <div>tdh at tkhanson.net</div>
+
+      </div> <!-- nav -->
+
+      <div id="main">
+
+<div>
+<div class="lead">Efficient serialization in C</div>
+You can use tpl to store and reload your C data quickly and easily.
+Tpl works with files, memory buffers and file descriptors so it's 
+suitable for use as a file format, IPC message format or any scenario
+where you need to store and retrieve your data.
+</div>
+
+<div>
+<div class="lead">Express your data</div>
+Just express the type of data you are working with as a tpl format string. For
+example, if you have a list of numeric ids and corresponding usernames, your
+format string is <em>A(is)</em>.  Map your C variables to the format string and
+then pack or unpack data.  The format string lets you focus on your data,
+rather than the storage format.
+</div>
+
+<div class="listing">
+<table summary="example of storing and reloading an integer array">
+<tr>
+<th>
+Storing ids and usernames
+</th>
+<th>
+Reloading ids and usernames
+</th>
+</tr>
+<tr>
+<td>
+<div class="code">
+<pre>
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    int id=0;
+    char *name, *names[] = { "joe", "bob", "cary" };
+
+    tn = tpl_map("A(is)", &amp;id, &amp;name);
+
+    for(name=names[0]; id &lt; 3; name=names[++id]) {
+        tpl_pack(tn,1);
+    }
+
+    tpl_dump(tn, TPL_FILE, "users.tpl");
+    tpl_free(tn);
+}
+</pre>
+</div> <!-- code -->
+</td>
+<td>
+<div class="code">
+<pre>
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    int id;
+    char *name;
+
+    tn = tpl_map("A(is)", &amp;id, &amp;name);
+    tpl_load(tn, TPL_FILE, "users.tpl");
+
+    while ( tpl_unpack(tn,1) &gt; 0 ) {
+        printf("id %d, user %s\n", id, name);
+        free(name);
+    }
+    tpl_free(tn);
+}
+</pre>
+</div> <!-- code -->
+</td>
+</tr>
+</table>
+</div> <!-- listing -->
+
+<div>
+<div class="lead">No library dependencies</div>
+Tpl does not make your software dependent on any libraries. You can compile its
+source code (one file) right into your program.
+</div>
+
+<div class="lead">For more information</div>
+For a more thorough explanation and more examples, please read the 
+<a href="userguide.html">User Guide.</a>
+
+</div> <!-- main -->
+</div> <!-- mid -->
+
+   <hr />
+  <div id="footer">
+    <a href="http://sourceforge.net/projects/tpl"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=157637&amp;type=13" width="120" height="30" alt="SourceForge.net." /></a>
+    <p>This project is hosted on SourceForge.net</p>
+    <p>$Id: index.html 192 2009-04-24 10:35:30Z thanson $</p>
+  </div> <!-- footer -->
+
+  </body>
+
+</html>
diff --git a/libs/libtpl-1.5/doc/html/license.html b/libs/libtpl-1.5/doc/html/license.html
new file mode 100755 (executable)
index 0000000..43aa2e9
--- /dev/null
@@ -0,0 +1,61 @@
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XTHML 1.0 Strict//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <link rel="stylesheet" type="text/css" href="styles.css" />
+    <title>tpl home page</title>
+  </head>
+  <body>
+
+  <div id="banner">
+  <img src="img/banner.png" alt="serialization in C: easy data storage and retrieval" />
+  </div> <!-- banner -->
+
+  <div id="topnav">
+  <a href="http://sourceforge.net/projects/tpl/">sf.net summary page</a> &gt;
+  <a href="index.html">tpl home</a> &gt;
+  BSD license
+  </div> <!-- topnav -->
+
+  <hr />
+  <div id="mid">
+
+
+      <div id="main">
+
+<pre>
+Copyright (c) 2005-2010, Troy D. Hanson    http://tpl.sourceforge.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:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+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.
+</pre>
+</div> <!-- main -->
+</div> <!-- mid -->
+
+   <hr />
+  <div id="footer">
+    <a href="http://sourceforge.net/projects/tpl"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=157637&amp;type=13" width="120" height="30" alt="SourceForge.net." /></a>
+    <p>This project is hosted on SourceForge.net</p>
+    <p>$Id: index.html 124 2007-04-27 06:41:36Z thanson $</p>
+  </div> <!-- footer -->
+
+  </body>
+
+</html>
diff --git a/libs/libtpl-1.5/doc/html/perl.html b/libs/libtpl-1.5/doc/html/perl.html
new file mode 100755 (executable)
index 0000000..c2baedf
--- /dev/null
@@ -0,0 +1,403 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.3.4" />\r
+<title>tpl Perl API</title>\r
+<link rel="stylesheet" href="./tdh.css" type="text/css" />\r
+<link rel="stylesheet" href="./tdh-quirks.css" type="text/css" />\r
+</head>\r
+<body>\r
+<div id="header">\r
+<h1>tpl Perl API</h1>\r
+<span id="author">Troy D. Hanson</span><br />\r
+<span id="email"><tt>&lt;<a href="mailto:troydhanson@comcast.net">troydhanson@comcast.net</a>&gt;</tt></span><br />\r
+<span id="revision">version 1.1,</span>\r
+April 2007\r
+</div>\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+<a style="float: right;" href="http://sourceforge.net/projects/tpl"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=157637&amp;type=16" width="150" height="40" alt="SourceForge.net" /></a>\r
+  <div id="topnav" style="font-size: 9pt; font-family: sans-serif;">\r
+  <a style="padding: 8px;" href="http://sourceforge.net/projects/tpl/">sf.net summary page</a> &gt;\r
+  <a style="padding: 8px;" href="index.html">tpl home</a> &gt;\r
+  tpl Perl API\r
+  <a style="padding: 8px;" href="userguide.pdf">[View PDF]</a>\r
+  </div>\r
+</div>\r
+</div>\r
+<h2 id="_perl_api">Perl API</h2>\r
+<div class="sectionbody">\r
+<div id="toc"></div>\r
+<script>\r
+window.onload=generate_TOC\r
+\r
+/* Author: Mihai Bazon, September 2002\r
+ * <a href="http://students.infoiasi.ro/~mishoo">http://students.infoiasi.ro/~mishoo</a>\r
+ *\r
+ * Table Of Content generator\r
+ * Version: 0.4\r
+ *\r
+ * Feel free to use this script under the terms of the GNU General Public\r
+ * License, as long as you do not remove or alter this notice.\r
+ */\r
+\r
+ /* modified by Troy D. Hanson, September 2006. License: GPL */\r
+\r
+function H_getText(el) {\r
+  var text = "";\r
+  for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+    if (i.nodeType == 3 /* Node.TEXT_NODE, IE doesn't speak constants */)\r
+      text += i.data;\r
+    else if (i.firstChild != null)\r
+      text += H_getText(i);\r
+  }\r
+  return text;\r
+}\r
+\r
+function TOC_EL(el, text, level) {\r
+  this.element = el;\r
+  this.text = text;\r
+  this.level = level;\r
+}\r
+\r
+function getHeadlines(el) {\r
+  var l = new Array;\r
+  var rx = /[hH]([2-3])/;\r
+  // internal recursive function that scans the DOM tree\r
+  var rec = function (el) {\r
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+      if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {\r
+        if (rx.exec(i.tagName))\r
+          l[l.length] = new TOC_EL(i, H_getText(i), parseInt(RegExp.$1));\r
+        rec(i);\r
+      }\r
+    }\r
+  }\r
+  rec(el);\r
+  return l;\r
+}\r
+\r
+function generate_TOC() {\r
+  var parent = document.getElementById("toc");\r
+  var toc_hdr = document.createElement("div");\r
+  var toc_hdr_txt = document.createTextNode("CONTENTS");\r
+  toc_hdr.appendChild(toc_hdr_txt);\r
+  /* toc_hdr.setAttribute("id","hdr"); */\r
+  toc_hdr.id = "hdr";\r
+  parent.appendChild(toc_hdr);\r
+  var hs = getHeadlines(document.getElementsByTagName("body")[0]);\r
+  for (var i = 0; i < hs.length; ++i) {\r
+    var hi = hs[i];\r
+    var d = document.createElement("div");\r
+    if (hi.element.id == "") hi.element.id = "gen" + i;\r
+    var a = document.createElement("a");\r
+    a.href = "#" + hi.element.id;\r
+    a.appendChild(document.createTextNode(hi.text));\r
+    d.appendChild(a);\r
+    d.className = "level" + hi.level;\r
+    parent.appendChild(d);\r
+    /*\r
+    if (hi.level == 3) {\r
+        var dvtop = document.createElement("div");\r
+        dvtop.className = "toplink";\r
+        dvtop.appendChild(document.createTextNode("^top^"));\r
+        dvtop.onclick=function(){scrollTo(0,0);};\r
+        hi.element.appendChild(dvtop);\r
+    }\r
+    */\r
+  }\r
+}\r
+</script>\r
+<div class="paragraph"><p>The Perl API for reading and writing tpl is nearly identical to the C API. This\r
+document will briefly explain the Perl API and provide examples. The chief\r
+motivation for having a Perl API is to communicate with C programs that use tpl.</p></div>\r
+<div class="admonitionblock">\r
+<table><tr>\r
+<td class="icon">\r
+<div class="title">Tip</div>\r
+</td>\r
+<td class="content">\r
+<div class="title">Start with the C API</div>This document assumes familiarity with the C API.  The concepts of using tpl\r
+are not explained here. For an introduction to tpl and its C API, see the\r
+<a href="userguide.html">User Guide</a>.</td>\r
+</tr></table>\r
+</div>\r
+<h3 id="_tpl_pm">Tpl.pm</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The <tt>Tpl.pm</tt> file (in the <tt>lang/perl</tt>) directory contains the Perl module.  You\r
+can copy it to another directory if you wish. Your Perl program may need to\r
+include a <tt>use lib</tt> statement to find the module.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>#!/usr/bin/perl\r
+use lib "/some/directory";\r
+use Tpl;</tt></pre>\r
+</div></div>\r
+<h3 id="_tpl_map">tpl_map</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This function resembles the C version, except that it&#8217;s invoked via the <tt>Tpl</tt>\r
+module, and it takes references to Perl variables after the format string.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>my $i;\r
+my $tpl = Tpl-&gt;tpl_map("A(i)",\$i);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The return value is a tpl object; all other API calls are object methods.\r
+Incidentally, there is no <tt>tpl_free()</tt> method corresponding to the C API.</p></div>\r
+<h4 id="_fixed_length_arrays">Fixed-length arrays</h4>\r
+<div class="paragraph"><p>Format strings such as <tt>i#</tt> denote a fixed-length array. In the Perl API,\r
+fixed-length arrays require two arguments: a list reference, and the fixed\r
+length. For example:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>my @x;\r
+my $tpl = Tpl-&gt;tpl_map("i#", \@x, 10);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>When fixed-length arrays are packed or unpacked, the specified number of\r
+elements will be copied from (or placed into) the designated list.</p></div>\r
+<h4 id="_structures">Structures</h4>\r
+<div class="paragraph"><p>Format strings containing <tt>S(&#8230;)</tt> are handled in the Perl API as if only the\r
+interior, parenthesized part was present. (It does not work like the C API). So\r
+simply ignore the <tt>S(&#8230;)</tt> and consider only its interior format characters when\r
+constructing the argument list:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>my ($str, $int);\r
+my $tpl = Tpl-&gt;tpl_map("S(si)", \$str, \$int);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>It really only makes sense to use <tt>S(&#8230;)</tt> in a format string in the Perl API if\r
+you are communicating with a C program that uses structures.</p></div>\r
+<h3 id="_tpl_pack">tpl_pack</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This is nearly identical to the C version. The only argument is the index\r
+number to pack.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>$tpl-&gt;tpl_pack(1);</tt></pre>\r
+</div></div>\r
+<h3 id="_tpl_dump">tpl_dump</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This method is a little different than the C version. Given no arguments, it\r
+returns the tpl image; given one argument it writes a file with that name.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>$tpl-&gt;tpl_dump("demo.tpl");   # writes demo.tpl</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Or,</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>my $img = $tpl-&gt;tpl_dump();</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The tpl image is a binary buffer. You can do whatever you want with it, such as\r
+write it to a socket or pipe (probably to C program listening on the other end),\r
+or save it somewhere and later re-load it using <tt>tpl_load()</tt>.</p></div>\r
+<h3 id="_tpl_load">tpl_load</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This method loads a tpl image from a file or from a Perl variable.  It takes\r
+one argument. If it&#8217;s not a reference, it&#8217;s assumed to be a filename to load.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>$tpl-&gt;tpl_load("demo.tpl");</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Otherwise, if the argument is a Perl reference, it&#8217;s construed as a variable\r
+containing the tpl image:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>$tpl-&gt;tpl_load(\$img);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The method will <tt>die</tt> if the image is invalid or the file doesn&#8217;t exist. You\r
+can wrap it with <tt>eval</tt> to catch such errors:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>eval { $tpl-&gt;tpl_load(\$img); };\r
+print "failed to load\n" if $@;</tt></pre>\r
+</div></div>\r
+<h3 id="_tpl_unpack">tpl_unpack</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This is nearly identical to the C version. The only argument is the index\r
+number to unpack.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>$tpl-&gt;tpl_unpack(1);</tt></pre>\r
+</div></div>\r
+</div>\r
+<h2 id="_examples">Examples</h2>\r
+<div class="sectionbody">\r
+<h3 id="_integer_array">Integer array</h3><div style="clear:left"></div>\r
+<div class="listingblock">\r
+<div class="title">Packing A(i) to file</div>\r
+<div class="content">\r
+<pre><tt>#!/usr/bin/perl\r
+\r
+use strict;\r
+use warnings;\r
+\r
+use Tpl;\r
+\r
+my $i;\r
+my $tpl = Tpl-&gt;tpl_map("A(i)",\$i);\r
+for($i=0; $i&lt;10; $i++) {\r
+    $tpl-&gt;tpl_pack(1);\r
+}\r
+$tpl-&gt;tpl_dump("demo.tpl");</tt></pre>\r
+</div></div>\r
+<div class="listingblock">\r
+<div class="title">Unpacking A(i) from file</div>\r
+<div class="content">\r
+<pre><tt>#!/usr/bin/perl\r
+\r
+use strict;\r
+use warnings;\r
+\r
+use Tpl;\r
+\r
+my $j;\r
+my $tpl2 = Tpl-&gt;tpl_map("A(i)",\$j);\r
+$tpl2-&gt;tpl_load("demo.tpl");\r
+while($tpl2-&gt;tpl_unpack(1) &gt; 0) {\r
+    print "$j\n";\r
+}</tt></pre>\r
+</div></div>\r
+<h3 id="_message_passing">Message-passing</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>While the bulk of this example is socket handling, it demonstrates how you can\r
+use tpl as a message-passing format. In the real-world, you might have a C\r
+server and a Perl client, for example. In this example, we&#8217;ll code both a client\r
+and a server in Perl.</p></div>\r
+<div class="sidebarblock">\r
+<div class="sidebar-content">\r
+<div class="sidebar-title">A server that sums integers</div>\r
+<div class="paragraph"><p>Programming literature is rife with contrived examples so we will follow in that\r
+tradition. Our server will do no more than sum a list of integers. But in doing\r
+so it will demonstrate message passing adequately. Both its input (the integer\r
+array) and its output (an integer) are tpl images, passed over a TCP/IP socket.</p></div>\r
+</div></div>\r
+<h4 id="_server">Server</h4>\r
+<div class="paragraph"><p>The server waits for a connection from a client. When it gets one, it accepts\r
+the connection and immediately forks a child process to handle it. Then it goes\r
+back to waiting for another new connection.</p></div>\r
+<div class="paragraph"><p>The server child process handles the client by loading and unpacking the tpl\r
+image sent by the client (containing an array of integers). It calculates their\r
+sum and constructs a new tpl image containing the sum, which it sends back to\r
+the client.</p></div>\r
+<div class="listingblock">\r
+<div class="title">Server</div>\r
+<div class="content">\r
+<pre><tt>#!/usr/bin/perl\r
+\r
+use strict;\r
+use warnings;\r
+\r
+use IO::Socket::INET;\r
+use Tpl;\r
+\r
+$SIG{CHLD} = "IGNORE"; # don't create zombies\r
+\r
+our $port = 2000;\r
+\r
+sub handle_client {\r
+    my $client = shift;\r
+\r
+    undef $/;\r
+    my $request = &lt;$client&gt;; # get request (slurp)\r
+\r
+    # read input array, and calculate total\r
+    my ($i,$total);\r
+    my $tpl = Tpl-&gt;tpl_map("A(i)", \$i);\r
+    eval { $tpl-&gt;tpl_load(\$request); };\r
+    die "received invalid tpl" if $@;\r
+    $total += $i while $tpl-&gt;tpl_unpack(1) &gt; 0;\r
+\r
+    # formulate response and send\r
+    my $tpl2 = Tpl-&gt;tpl_map("i", \$total);\r
+    $tpl2-&gt;tpl_pack(0);\r
+    my $response = $tpl2-&gt;tpl_dump();\r
+    print $client $response;\r
+    close $client;\r
+}\r
+\r
+my $server = IO::Socket::INET-&gt;new(LocalPort =&gt; $port,\r
+                   Type =&gt; SOCK_STREAM,\r
+                   Reuse =&gt; 1,\r
+                   Listen =&gt; 10 )\r
+        or die "Can't listen on port $port: $!\n";\r
+\r
+while (1) {\r
+    my $client = $server-&gt;accept();\r
+    next unless $client;\r
+    # new connection\r
+    my $pid = fork;\r
+    die "can't fork: $!\n" unless defined $pid;\r
+    if ($pid &gt; 0) {\r
+        # parent\r
+        close $client;\r
+    } elsif ($pid == 0) {\r
+        # child\r
+        handle_client($client);\r
+        exit(0);\r
+    }\r
+}\r
+close ($server);</tt></pre>\r
+</div></div>\r
+<h4 id="_client">Client</h4>\r
+<div class="paragraph"><p>The client is a simpler program. It constructs the tpl image containing the\r
+integer array (taken from its command-line arguments), connects to the server\r
+and sends the tpl image to it, and then awaits the response tpl. The response\r
+containing the sum is loaded, unpacked and printed.</p></div>\r
+<div class="listingblock">\r
+<div class="title">Client</div>\r
+<div class="content">\r
+<pre><tt>#!/usr/bin/perl\r
+\r
+use strict;\r
+use warnings;\r
+\r
+use IO::Socket::INET;\r
+use Tpl;\r
+\r
+our $port = 2000;\r
+\r
+# construct tpl\r
+my $i;\r
+my $tpl = Tpl-&gt;tpl_map("A(i)",\$i);\r
+$tpl-&gt;tpl_pack(1) while ($i=shift @ARGV);\r
+my $request = $tpl-&gt;tpl_dump();\r
+\r
+# send to server, get response\r
+my $socket = IO::Socket::INET-&gt;new("localhost:$port") or die "can't connect";\r
+print $socket $request;\r
+shutdown($socket,1);        # done writing (half-close)\r
+undef $/;\r
+my $response = &lt;$socket&gt;;       # get reply (slurp)\r
+\r
+# decode response (or print error)\r
+my $total;\r
+my $tpl2 = Tpl-&gt;tpl_map("i", \$total);\r
+eval { $tpl2-&gt;tpl_load(\$response); };\r
+die "invalid response\n" if $@;\r
+$tpl2-&gt;tpl_unpack(0);\r
+print "total is $total\n";</tt></pre>\r
+</div></div>\r
+<h4 id="_running_thise_example">Running thise example</h4>\r
+<div class="paragraph"><p>If the client and server programs are in <tt>client.pl</tt> and <tt>server.pl</tt>, then\r
+you can run the example by starting the server in one window:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>./server.pl</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Then run the client in another window. E.g.,</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>./client.pl 1 2 3 4 5</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The client runs and then exits, printing:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>total is 15</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>You can re-run the client with different arguments. When done, type <tt>Ctrl-C</tt> in\r
+the server window to terminate it.</p></div>\r
+</div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Version 1.1<br />\r
+Last updated 2009-04-30 21:22:12 EDT\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/libs/libtpl-1.5/doc/html/styles.css b/libs/libtpl-1.5/doc/html/styles.css
new file mode 100755 (executable)
index 0000000..c23156e
--- /dev/null
@@ -0,0 +1,160 @@
+#banner {
+    /* font-size: x-large; */
+    /* background: #ff00ff; */
+    /* height: 100px; */
+}
+
+#topnav {
+    /* background-image: url(img/grad_topnav.png); */
+    /* background-repeat: repeat-y; */
+    /* background-color: #af00af; */
+    /* height: 25px; */
+    margin: 10px 0px 10px 20px;
+    padding: 3px;
+    font-size: 9pt;
+    font-family: sans-serif;
+    /* border-style: solid; */
+    /* border-width: 1px; */
+}
+
+
+#topnav  {font-weight: bold}
+#topnav a {font-weight: normal}
+
+h1,p {  margin: 0; }  /* non-0 margin on firefox */
+
+#mid {
+    background-image: url(img/grad_azure.png);
+    background-repeat: repeat-y;
+    /* background-color: #ffddaa; */
+    padding-top: 20px;
+    margin-bottom: 10px;
+}
+
+#mid img {
+    padding-left: 10px;
+    vertical-align: middle;
+}
+
+a img {
+   border: 0
+}
+
+#nav {
+    background-color: #fff8f1;
+    margin-left: 10px;
+    margin-top: 20px;
+    float: left;
+    padding: 10px;
+    border-style: solid;
+    border-width: 2px;
+    font-family: sans-serif;
+}
+
+
+#nav h2 {
+    font-weight: bold;
+    font-size: 10pt;
+}
+
+#nav h3 {
+    /* font-weight: bold; */
+    padding-left: 5px;
+    /* font-style: oblique;  */
+    font-family: sans-serif;
+    font-size: 7pt;
+}
+
+#nav div {
+    font-size: 9pt;
+    padding-left: 15px;
+}
+
+#main {
+    background: #ffffff;
+    margin-top: 20px;
+    margin-left: 170px;
+    padding-left: 20px;
+    height: 100%;
+    /* font-family: sans-serif; */
+}
+
+#main h1 {
+    font-family: sans-serif;
+}
+
+
+.listing {
+    margin: 20px;
+    font-family: sans-serif;
+    font-weight: bold;
+}
+
+.code {
+    padding: 10px;
+    background: #f3f3f3;
+    font-size: 8pt;
+    font-weight: normal;
+    width: 80%;
+    border-style: solid;
+    border-width: 1px;
+}
+
+.code pre {
+    padding-left: 20px;
+    padding-right: 80px;
+}
+
+#formatstrings {
+    margin: 20px;
+}
+
+#footer {
+    /* background: #00ffff; */
+    margin-top: 5px;
+    font-size: small;
+    font-family: sans-serif;
+}
+
+em {
+    font-weight: bold;
+}
+
+hr {
+    height: 0.04em;
+    background: black;
+    margin: 0 10% 0 0;
+}
+
+#footer img {
+    margin-right: 5px;
+    float: right;
+}
+
+.lead {
+    font-family: sans-serif;
+    font-size: larger;
+    font-weight: bold;
+    /* font-style: oblique; */
+    margin: 30px 30px 30px 0px;
+    color: #1122dd;
+}
+
+ol {
+    font-family: monospace;
+    background: #dddddd;
+    padding-top: 10px;
+    padding-bottom: 10px;
+    width: 80%;
+    border-width: 1px;
+    border-style: solid;
+    /* font-size: smaller; */
+}
+
+#main #portrait {
+    float: right;
+    font-size: smaller;
+    font-family: sans-serif;
+    text-align: center;
+    margin: 10px;
+}
diff --git a/libs/libtpl-1.5/doc/html/tdh-quirks.css b/libs/libtpl-1.5/doc/html/tdh-quirks.css
new file mode 100755 (executable)
index 0000000..7478972
--- /dev/null
@@ -0,0 +1,31 @@
+/* Workarounds for IE6's broken and incomplete CSS2. */
+
+div.sidebar-content {
+  background: #ffffee;
+  border: 1px solid silver;
+  padding: 0.5em;
+}
+div.sidebar-title, div.image-title {
+  font-family: sans-serif;
+  font-weight: bold;
+  margin-top: 0.0em;
+  margin-bottom: 0.5em;
+}
+
+div.listingblock div.content {
+  border: 1px solid silver;
+  background: #f4f4f4;
+  padding: 0.5em;
+}
+
+div.quoteblock-content {
+  padding-left: 2.0em;
+}
+
+div.exampleblock-content {
+  border-left: 2px solid silver;
+  padding-left: 0.5em;
+}
+
+/* IE6 sets dynamically generated links as visited. */
+div#toc a:visited { color: blue; }
diff --git a/libs/libtpl-1.5/doc/html/tdh.css b/libs/libtpl-1.5/doc/html/tdh.css
new file mode 100755 (executable)
index 0000000..b9679f3
--- /dev/null
@@ -0,0 +1,301 @@
+/* Debug borders */
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
+/*
+  border: 1px solid red;
+*/
+}
+
+body {
+  margin: 1em 5% 1em 5%;
+}
+
+a {
+  color: blue;
+  text-decoration: underline;
+}
+a:visited {
+  color: fuchsia;
+}
+
+em {
+  font-style: italic;
+}
+
+strong {
+  font-weight: bold;
+}
+
+tt {
+  color: navy;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  color: #527bbd;
+  font-family: sans-serif;
+  margin-top: 1.2em;
+  margin-bottom: 0.5em;
+  line-height: 1.3;
+}
+
+h1, h2, h3 {
+  border-bottom: 2px solid silver;
+}
+h2 {
+  padding-top: 0.5em;
+}
+h3 {
+  float: left;
+}
+h3 + * {
+  clear: left;
+}
+
+div.sectionbody {
+  font-family: serif;
+  margin-left: 0;
+}
+
+hr {
+  border: 1px solid silver;
+}
+
+p {
+  margin-top: 0.5em;
+  margin-bottom: 0.5em;
+}
+
+pre {
+  padding: 0;
+  margin: 0;
+}
+
+span#author {
+  color: #527bbd;
+  font-family: sans-serif;
+  font-weight: bold;
+  font-size: 1.1em;
+}
+span#email {
+}
+span#revision {
+  font-family: sans-serif;
+}
+
+div#footer {
+  font-family: sans-serif;
+  font-size: small;
+  border-top: 2px solid silver;
+  padding-top: 0.5em;
+  margin-top: 4.0em;
+}
+div#footer-text {
+  float: left;
+  padding-bottom: 0.5em;
+}
+div#footer-badges {
+  float: right;
+  padding-bottom: 0.5em;
+}
+
+div#preamble,
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+  margin-right: 10%;
+  margin-top: 1.5em;
+  margin-bottom: 1.5em;
+}
+div.admonitionblock {
+  margin-top: 2.5em;
+  margin-bottom: 2.5em;
+}
+
+div.content { /* Block element content. */
+  padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+  font-family: sans-serif;
+  font-weight: bold;
+  text-align: left;
+  margin-top: 1.0em;
+  margin-bottom: 0.5em;
+}
+div.title + * {
+  margin-top: 0;
+}
+
+td div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content + div.title {
+  margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+  background: #ffffee;
+  border: 1px solid silver;
+  padding: 0.5em;
+}
+
+div.listingblock {
+  margin-right: 0%;
+}
+div.listingblock > div.content {
+  border: 1px solid silver;
+  background: #f4f4f4;
+  padding: 0.5em;
+}
+
+div.quoteblock > div.content {
+  padding-left: 2.0em;
+}
+
+div.attribution {
+  text-align: right;
+}
+div.verseblock + div.attribution {
+  text-align: left;
+}
+
+div.admonitionblock .icon {
+  vertical-align: top;
+  font-size: 1.1em;
+  font-weight: bold;
+  text-decoration: underline;
+  color: #527bbd;
+  padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+  padding-left: 0.5em;
+  border-left: 2px solid silver;
+}
+
+div.exampleblock > div.content {
+  border-left: 2px solid silver;
+  padding: 0.5em;
+}
+
+div.verseblock div.content {
+  white-space: pre;
+}
+
+div.imageblock div.content { padding-left: 0; }
+div.imageblock img { border: 1px solid silver; }
+span.image img { border-style: none; }
+
+dl {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+dt {
+  margin-top: 0.5em;
+  margin-bottom: 0;
+  font-style: italic;
+}
+dd > *:first-child {
+  margin-top: 0;
+}
+
+ul, ol {
+    list-style-position: outside;
+}
+div.olist2 ol {
+  list-style-type: lower-alpha;
+}
+
+div.tableblock > table {
+  border: 3px solid #527bbd;
+}
+thead {
+  font-family: sans-serif;
+  font-weight: bold;
+}
+tfoot {
+  font-weight: bold;
+}
+
+div.hlist {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+div.hlist td {
+  padding-bottom: 5px;
+}
+td.hlist1 {
+  vertical-align: top;
+  font-style: italic;
+  padding-right: 0.8em;
+}
+td.hlist2 {
+  vertical-align: top;
+}
+
+@media print {
+  div#footer-badges { display: none; }
+}
+
+div#toctitle {
+  color: #527bbd;
+  font-family: sans-serif;
+  font-size: 1.1em;
+  font-weight: bold;
+  margin-top: 1.0em;
+  margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+div.toclevel2 {
+  margin-left: 2em;
+  font-size: 0.9em;
+}
+div.toclevel3 {
+  margin-left: 4em;
+  font-size: 0.9em;
+}
+div.toclevel4 {
+  margin-left: 6em;
+  font-size: 0.9em;
+}
+#toc {
+  float: right;
+  font-family: sans-serif; 
+  border: 1px solid #000;
+  margin: 0px 0px 20px 20px;
+  padding: 0px;
+  background: #f0f0f0;
+  font-size: 80%;
+}
+
+#toc #hdr {
+  color:#ffffff;
+  background:#98b1c4;
+  text-align:center;
+  margin-bottom:5px;
+}
+
+a img {
+   border: 0
+}
+
+#toc a:visited, #toc a:link { color:#000; text-decoration: none }
+#toc a:hover { color:#00f; text-decoration: underline; }
+
+#toc .level2 { margin-left: 1em; margin-top: 2px; margin-bottom: 2px; text-decoration: underline; }
+#toc .level3 { margin-left: 2em; font-size: 0.8em }
+
+.toplink {
+    float: right;
+    font-size: 50%;
+    cursor: pointer;
+}
+
+#topnav  {font-weight: bold}
+#topnav a {font-weight: normal}
diff --git a/libs/libtpl-1.5/doc/html/toc.css b/libs/libtpl-1.5/doc/html/toc.css
new file mode 100755 (executable)
index 0000000..ae3363e
--- /dev/null
@@ -0,0 +1,35 @@
+#toc {
+  float: right;
+  font-family: sans-serif; 
+  border: 1px solid #000;
+  margin: 0px 0px 20px 20px;
+  padding: 0px;
+  background: #f0f0f0;
+  font-size: 80%;
+}
+
+#toc #hdr {
+  color:#ffffff;
+  background:#98b1c4;
+  text-align:center;
+  margin-bottom:5px;
+}
+
+a img {
+   border: 0
+}
+
+#toc a:visited, #toc a:link { color:#000; text-decoration: none }
+#toc a:hover { color:#00f; text-decoration: underline; }
+
+#toc .level2 { margin-left: 1em; margin-top: 2px; margin-bottom: 2px; text-decoration: underline; }
+#toc .level3 { margin-left: 2em; font-size: 0.8em }
+
+.toplink {
+    float: right;
+    font-size: 50%;
+    cursor: pointer;
+}
+
+#topnav  {font-weight: bold}
+#topnav a {font-weight: normal}
diff --git a/libs/libtpl-1.5/doc/html/userguide.html b/libs/libtpl-1.5/doc/html/userguide.html
new file mode 100755 (executable)
index 0000000..368a605
--- /dev/null
@@ -0,0 +1,1539 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.3.4" />\r
+<title>tpl User Guide</title>\r
+<link rel="stylesheet" href="./tdh.css" type="text/css" />\r
+<link rel="stylesheet" href="./tdh-quirks.css" type="text/css" />\r
+</head>\r
+<body>\r
+<div id="header">\r
+<h1>tpl User Guide</h1>\r
+<span id="author">Troy D. Hanson</span><br />\r
+<span id="email"><tt>&lt;<a href="mailto:thanson@users.sourceforge.net">thanson@users.sourceforge.net</a>&gt;</tt></span><br />\r
+<span id="revision">version 1.5,</span>\r
+February 2010\r
+</div>\r
+<div id="preamble">\r
+<div class="sectionbody">\r
+<a style="float: right;" href="http://sourceforge.net/projects/tpl"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=157637&amp;type=16" width="150" height="40" alt="SourceForge.net" /></a>\r
+  <div id="topnav" style="font-size: 9pt; font-family: sans-serif;">\r
+  <a style="padding: 8px;" href="http://sourceforge.net/projects/tpl/">sf.net summary page</a> &gt;\r
+  <a style="padding: 8px;" href="index.html">tpl home</a> &gt;\r
+  tpl User Guide\r
+  <a style="padding: 8px;" href="userguide.pdf">[View PDF]</a>\r
+  </div>\r
+</div>\r
+</div>\r
+<h2 id="_overview">Overview</h2>\r
+<div class="sectionbody">\r
+<div id="toc"></div>\r
+<script>\r
+window.onload=generate_TOC\r
+\r
+/* Author: Mihai Bazon, September 2002\r
+ * <a href="http://students.infoiasi.ro/~mishoo">http://students.infoiasi.ro/~mishoo</a>\r
+ *\r
+ * Table Of Content generator\r
+ * Version: 0.4\r
+ *\r
+ * Feel free to use this script under the terms of the GNU General Public\r
+ * License, as long as you do not remove or alter this notice.\r
+ */\r
+\r
+ /* modified by Troy D. Hanson, September 2006. License: GPL */\r
+\r
+function H_getText(el) {\r
+  var text = "";\r
+  for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+    if (i.nodeType == 3 /* Node.TEXT_NODE, IE doesn't speak constants */)\r
+      text += i.data;\r
+    else if (i.firstChild != null)\r
+      text += H_getText(i);\r
+  }\r
+  return text;\r
+}\r
+\r
+function TOC_EL(el, text, level) {\r
+  this.element = el;\r
+  this.text = text;\r
+  this.level = level;\r
+}\r
+\r
+function getHeadlines(el) {\r
+  var l = new Array;\r
+  var rx = /[hH]([2-3])/;\r
+  // internal recursive function that scans the DOM tree\r
+  var rec = function (el) {\r
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+      if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {\r
+        if (rx.exec(i.tagName))\r
+          l[l.length] = new TOC_EL(i, H_getText(i), parseInt(RegExp.$1));\r
+        rec(i);\r
+      }\r
+    }\r
+  }\r
+  rec(el);\r
+  return l;\r
+}\r
+\r
+function generate_TOC() {\r
+  var parent = document.getElementById("toc");\r
+  var toc_hdr = document.createElement("div");\r
+  var toc_hdr_txt = document.createTextNode("CONTENTS");\r
+  toc_hdr.appendChild(toc_hdr_txt);\r
+  /* toc_hdr.setAttribute("id","hdr"); */\r
+  toc_hdr.id = "hdr";\r
+  parent.appendChild(toc_hdr);\r
+  var hs = getHeadlines(document.getElementsByTagName("body")[0]);\r
+  for (var i = 0; i < hs.length; ++i) {\r
+    var hi = hs[i];\r
+    var d = document.createElement("div");\r
+    if (hi.element.id == "") hi.element.id = "gen" + i;\r
+    var a = document.createElement("a");\r
+    a.href = "#" + hi.element.id;\r
+    a.appendChild(document.createTextNode(hi.text));\r
+    d.appendChild(a);\r
+    d.className = "level" + hi.level;\r
+    parent.appendChild(d);\r
+    /*\r
+    if (hi.level == 3) {\r
+        var dvtop = document.createElement("div");\r
+        dvtop.className = "toplink";\r
+        dvtop.appendChild(document.createTextNode("^top^"));\r
+        dvtop.onclick=function(){scrollTo(0,0);};\r
+        hi.element.appendChild(dvtop);\r
+    }\r
+    */\r
+  }\r
+}\r
+</script>\r
+<h3 id="_serialization_in_c">Serialization in C</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Tpl is a library for serializing C data. The data is stored in its natural\r
+binary form. The API is small and tries to stay "out of the way".\r
+Tpl can serialize many C data types, including structures.</p></div>\r
+<h3 id="_uses_for_tpl">Uses for tpl</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Tpl makes a convenient file format. For example, suppose a program needs to\r
+store a list of user names and ids. This can be expressed using the format\r
+string <tt>A(si)</tt>.  If the program needs two such lists (say, one for regular\r
+users and one for administrators) this could be expressed as <tt>A(si)A(si)</tt>. It\r
+is easy to read and write this kind of structured data using tpl.</p></div>\r
+<div class="paragraph"><p>Tpl can also be used as an IPC message format. It handles byte order issues\r
+and deframing individual messages off of a stream automatically.</p></div>\r
+<h3 id="_expressing_type">Expressing type</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The "data type" of a tpl is explicitly stated as a format string. There is\r
+never any ambiguity about the type of data stored in a tpl.  Some examples:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+<tt>A(is)</tt> is a variable-length array of integer-string pairs\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>A(is)A(is)</tt> are two such arrays, completely independent of one another\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>S(ci)</tt> is a structure containing a char and integer\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>S(ci)#</tt> is a fixed-length array of the latter structure\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<tt>A(A(i))</tt> is a nested array, that is, an array of integer arrays\r
+</p>\r
+</li>\r
+</ul></div>\r
+<h3 id="_the_tpl_image">The tpl image</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>A tpl image is the serialized form of a tpl, stored in a memory buffer or file,\r
+or written to a file descriptor.</p></div>\r
+<h4 id="_what_8217_s_in_a_tpl_image">What&#8217;s in a tpl image?</h4>\r
+<div class="paragraph"><p>There is no need to understand the internal structure of the tpl image. But for the\r
+curious, the image is a strictly defined binary buffer having two sections,\r
+a header and the data.  The header encodes the length of the image, its\r
+format string, endian order and other flags. The data section contains the\r
+packed data.</p></div>\r
+<h4 id="_no_framing_needed">No framing needed</h4>\r
+<div class="paragraph"><p>A property of the tpl image is that consecutive images can be written to a stream\r
+without requiring any delimiter between them. The reader making use of\r
+<tt>tpl_gather</tt> (or <tt>tpl_load</tt> in <tt>TPL_FD</tt> mode) will obtain exactly one tpl image at\r
+a time.  Therefore tpl images can be used as an IPC message format without any\r
+higher-level framing protocol.</p></div>\r
+<h4 id="_data_portability">Data portability</h4>\r
+<div class="paragraph"><p>A tpl image generated on one kind of CPU will generally be portable to other\r
+CPU types when tpl is used properly. This may be a surprise considering that\r
+tpl is a binary format. But tpl has been carefully designed to make this work.\r
+Each <a href="#types">format character</a> has an associated explicitly-sized type. For\r
+integer and floating point types, whose "endian" or byte-order convention varies\r
+from one CPU to another, tpl automatically and transparently corrects the\r
+endian order (if needed) during the unpacking process.  Floating point numbers\r
+present their own <a href="#trouble_with_double">special difficulties</a>. <em>No guarantees\r
+are made with regard to floating point portability.</em> That said, because many\r
+modern CPU&#8217;s use IEEE 754 floating point representation, data is likely to be\r
+portable among them.</p></div>\r
+<h3 id="_xml_and_perl">XML and Perl</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p><em>Note: The <tt>tplxml</tt> utility and the Perl module are currently unsupported in tpl 1.5.</em></p></div>\r
+<h4 id="_xml">XML</h4>\r
+<div class="paragraph"><p>While a tpl image is a binary entity, you can view any tpl image in XML format\r
+using the included <tt>tplxml</tt> utility, located in the <tt>lang/perl</tt> directory.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tplxml file.tpl &gt; file.xml\r
+tplxml file.xml &gt; file.tpl</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The utility is bidirectional, as shown.  The file extension is not important;\r
+<tt>tplxml</tt> inspects its input to see if it&#8217;s tpl or XML. You can also pipe data\r
+into it instead of giving it a filename. The <tt>tplxml</tt> utility is slow. Its\r
+purpose is two-fold: debugging (manual inspection of the data in a tpl), and\r
+interoperability with XML-based programs.  The resulting XML is often ten times\r
+the size of the original binary tpl image.</p></div>\r
+<h4 id="_perl">Perl</h4>\r
+<div class="paragraph"><p>There is a Perl module in <tt>lang/perl/Tpl.pm</tt>. The <a href="perl.html">Perl API</a>\r
+is convenient for writing Perl scripts that interoperate with C programs, and\r
+need to pass structured data back and forth. It is written in pure Perl.</p></div>\r
+<h3 id="_platforms">Platforms</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The tpl software was developed for POSIX systems and has been tested on 32- and 64-bit\r
+platforms including:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Linux\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Solaris\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Mac OS X\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+OpenBSD\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Windows using Visual Studio 2008 or 2010, or Cygwin or MinGW\r
+</p>\r
+</li>\r
+</ul></div>\r
+<h3 id="_bsd_licensed">BSD licensed</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This software is made available under the\r
+<a href="license.html">revised BSD license</a>.\r
+It is free and open source.</p></div>\r
+<h3 id="_download">Download</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Please follow the link to download on the\r
+<a href="http://tpl.sourceforge.net">tpl website</a>.</p></div>\r
+<h3 id="_getting_help">Getting help</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>If you need help, you are welcome to email the author at\r
+<a href="mailto:thanson@users.sourceforge.net">thanson@users.sourceforge.net</a>.</p></div>\r
+<h3 id="_resources">Resources</h3><div style="clear:left"></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+News\r
+</dt>\r
+<dd>\r
+<p>\r
+ The author has a news feed for <a href="http://troydhanson.wordpress.com/feed/">software updates</a> <span class="image">\r
+<img src="img/rss.png" alt="(RSS)" title="(RSS)" />\r
+</span>.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+<h2 id="_build_and_install">Build and install</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Tpl has no dependencies on libraries other than the system C library. You\r
+can simply copy the tpl source into your project, so you have no dependencies.\r
+Alternatively, you can build tpl as a library and link it to your program.</p></div>\r
+<h3 id="_as_source">As source</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The simplest way to use tpl is to copy the source files <tt>tpl.h</tt> and <tt>tpl.c</tt>\r
+(from the <tt>src/</tt> directory) right into your project, and build them with the\r
+rest of your source files. No special compiler flags are required.</p></div>\r
+<h3 id="_as_a_library">As a library</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Alternatively, to build tpl as a library, from the top-level directory, run:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>./configure\r
+make\r
+make install</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>This installs a static library <tt>libtpl.a</tt> and a shared library (e.g.,\r
+<tt>libtpl.so</tt>), if your system supports them, in standard places. The installation\r
+directory can be customized using <tt>./configure --prefix=/some/directory</tt>. Run\r
+<tt>configure --help</tt> for further options.</p></div>\r
+<h4 id="_test_suite">Test suite</h4>\r
+<div class="paragraph"><p>You can compile and run the built-in test suite by running:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>cd tests/\r
+make</tt></pre>\r
+</div></div>\r
+<h3 id="_on_windows">On Windows</h3><div style="clear:left"></div>\r
+<h4 id="_dll">DLL</h4>\r
+<div class="paragraph"><p>On the tpl home page, a Visual Studio 2008 solution package is available for\r
+download.  This zip file contains pre-built 32- and 64-bit versions of tpl as a\r
+DLL.  If you like, you can build the DLL yourself using  VS2008 or VS2010 (the\r
+free Express Edition is sufficient) by opening the solution file and choosing\r
+Build Solution.</p></div>\r
+<h4 id="_non_dll_usage">Non-DLL usage</h4>\r
+<div class="paragraph"><p>Alternatively, tpl can be used directly (instead of as a DLL) by compiling\r
+the tpl sources right into your program. To do this, add <tt>tpl.c</tt>, <tt>tpl.h</tt>,\r
+<tt>win/mman.h</tt> and <tt>win/mmap.c</tt> to your program&#8217;s source and header files and\r
+add the preprocessor definition <tt>TPL_NOLIB</tt>.</p></div>\r
+<h4 id="_mingw_cygwin">MinGW/Cygwin</h4>\r
+<div class="paragraph"><p>Prior to tpl release 1.5, using tpl on Windows required building it with MinGW\r
+or Cygwin. This is no longer necessary. If you want to build it that way anyway,\r
+use the non-Windows (i.e. tar.bz2) tpl download and follow the "configure; make;\r
+make install" approach.</p></div>\r
+</div>\r
+<h2 id="_api_concepts">API concepts</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>To use tpl, you need to know the order in which to call the API functions, and\r
+the background concepts of format string, arrays and index numbers.</p></div>\r
+<h3 id="_order_of_functions">Order of functions</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Creating a tpl is always the first step, and freeing it is the last step. In\r
+between, you either pack and dump the tpl (if you&#8217;re serializing data) or you\r
+load a tpl image and unpack it (if you&#8217;re deserializing data).</p></div>\r
+<div class="tableblock">\r
+<table rules="none"\r
+width="50%"\r
+frame="border"\r
+cellspacing="0" cellpadding="4">\r
+<caption class="title">Order of usage</caption>\r
+<col width="9%" />\r
+<col width="45%" />\r
+<col width="45%" />\r
+<thead valign="top">\r
+<tr>\r
+<th align="center">Step  </th>\r
+<th align="center">     If you&#8217;re serializing&#8230;</th>\r
+<th align="center">      If you&#8217;re deserializing&#8230;</th>\r
+</tr>\r
+</thead>\r
+<tbody valign="top">\r
+<tr>\r
+<td align="center"><p class="table">1.</p></td>\r
+<td align="center"><p class="table"><tt>tpl_map()</tt></p></td>\r
+<td align="center"><p class="table"><tt>tpl_map()</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table">2.</p></td>\r
+<td align="center"><p class="table"><tt>tpl_pack()</tt></p></td>\r
+<td align="center"><p class="table"><tt>tpl_load()</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table">3.</p></td>\r
+<td align="center"><p class="table"><tt>tpl_dump()</tt></p></td>\r
+<td align="center"><p class="table"><tt>tpl_unpack()</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table">4.</p></td>\r
+<td align="center"><p class="table"><tt>tpl_free()</tt></p></td>\r
+<td align="center"><p class="table"><tt>tpl_free()</tt></p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<h3 id="format">Format string</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>When a tpl is created using <tt>tpl_map()</tt>, its data type is expressed as a format\r
+string.  Each character in the format string has an associated argument of a\r
+specific type.  For example, this is how a format string and its arguments are\r
+passed in to <tt>tpl_map</tt>:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tpl_node *tn;\r
+char c;\r
+int i[10];\r
+tn = tpl_map("ci#", &amp;c, i, 10);  /* ci# is our format string */</tt></pre>\r
+</div></div>\r
+<div class="tableblock" id="types">\r
+<table rules="none"\r
+width="90%"\r
+frame="border"\r
+cellspacing="0" cellpadding="4">\r
+<caption class="title">Supported format characters</caption>\r
+<col width="11%" />\r
+<col width="44%" />\r
+<col width="44%" />\r
+<thead valign="top">\r
+<tr>\r
+<th align="center">Type </th>\r
+<th align="left">  Description                                             </th>\r
+<th align="left"> Required argument type</th>\r
+</tr>\r
+</thead>\r
+<tbody valign="top">\r
+<tr>\r
+<td align="center"><p class="table"><tt>j</tt></p></td>\r
+<td align="left"><p class="table">16-bit signed int</p></td>\r
+<td align="left"><p class="table">int16_t* or equivalent</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>v</tt></p></td>\r
+<td align="left"><p class="table">16-bit unsigned int</p></td>\r
+<td align="left"><p class="table">uint16_t* or equivalent</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>i</tt></p></td>\r
+<td align="left"><p class="table">32-bit signed int</p></td>\r
+<td align="left"><p class="table">int32_t* or equivalent</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>u</tt></p></td>\r
+<td align="left"><p class="table">32-bit unsigned int</p></td>\r
+<td align="left"><p class="table">uint32_t* or equivalent</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>I</tt></p></td>\r
+<td align="left"><p class="table">64-bit signed int</p></td>\r
+<td align="left"><p class="table">int64_t* or equivalent</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>U</tt></p></td>\r
+<td align="left"><p class="table">64-bit unsigned int</p></td>\r
+<td align="left"><p class="table">uint64_t* or equivalent</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>c</tt></p></td>\r
+<td align="left"><p class="table">character (byte)</p></td>\r
+<td align="left"><p class="table">char*</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>s</tt></p></td>\r
+<td align="left"><p class="table">string</p></td>\r
+<td align="left"><p class="table">char**</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>f</tt></p></td>\r
+<td align="left"><p class="table">64-bit double precision float</p></td>\r
+<td align="left"><p class="table">double* (varies by platform)</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>#</tt></p></td>\r
+<td align="left"><p class="table">array length; modifies preceding <tt>iujvIUcsf</tt> or <tt>S(&#8230;)</tt></p></td>\r
+<td align="left"><p class="table">int</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>B</tt></p></td>\r
+<td align="left"><p class="table">binary buffer (arbitrary-length)</p></td>\r
+<td align="left"><p class="table">tpl_bin*</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>S</tt></p></td>\r
+<td align="left"><p class="table">structure (&#8230;)</p></td>\r
+<td align="left"><p class="table">struct *</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>$</tt></p></td>\r
+<td align="left"><p class="table">nested structure (&#8230;)</p></td>\r
+<td align="left"><p class="table">none</p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table"><tt>A</tt></p></td>\r
+<td align="left"><p class="table">array (&#8230;)</p></td>\r
+<td align="left"><p class="table">none</p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<h4 id="_explicit_sizes">Explicit sizes</h4>\r
+<div class="paragraph"><p>The sizes of data types such as <tt>long</tt> and <tt>double</tt> vary by platform. This must\r
+be kept in mind because most tpl format characters require a pointer argument to\r
+a specific-sized type, listed above. You can use explicit-sized types such as\r
+<tt>int32_t</tt> (defined in <tt>inttypes.h</tt>) in your program if you find this helpful.</p></div>\r
+<h5 id="trouble_with_double">The trouble with double</h5>\r
+<div class="paragraph"><p>Unfortunately there are no standard explicit-sized floating-point types-- no\r
+<tt>float64_t</tt>, for example. If you plan to serialize <tt>double</tt> on your platform\r
+using tpl&#8217;s <tt>f</tt> format character, first be sure that your <tt>double</tt> is 64 bits.\r
+Second, if you plan to deserialize it on a different kind of CPU, be sure that\r
+both CPU&#8217;s use the same floating-point representation such as IEEE 754.</p></div>\r
+<h3 id="arrays">Arrays</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Arrays come in two kinds: <strong>fixed-length</strong> and <strong>variable-length</strong> arrays.\r
+Intuitively, they can be thought of like conventional C arrays and linked lists.\r
+In general, use fixed-length arrays if possible, and variable-length arrays\r
+if necessary. The variable-length arrays support more complex data types, and\r
+give or receive the elements to your program one by one.</p></div>\r
+<h4 id="_fixed_length_vs_variable_length_arrays">Fixed-length vs. Variable-length arrays</h4>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+Notation\r
+</dt>\r
+<dd>\r
+<p>\r
+    Fixed-length arrays are denoted like <tt>i#</tt> (a simple type followed by one or\r
+    more <tt>#</tt> signs), but variable-length arrays are denoted like <tt>A(i)</tt>.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+Element handling\r
+</dt>\r
+<dd>\r
+<p>\r
+    All the elements of a fixed-length array are packed or unpacked at once. But\r
+    the elements of a variable-length array are packed or unpacked one by one.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+Array length\r
+</dt>\r
+<dd>\r
+<p>\r
+    The number of elements in a fixed-length array is specified before use--\r
+    before any data is packed. But variable-length arrays do not have a fixed\r
+    element count. They can have any number of elements packed into them. When\r
+    unpacking a variable-length array, they are unpacked one by one until they\r
+    are exhausted.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+Element types\r
+</dt>\r
+<dd>\r
+<p>\r
+    Elements of fixed-length arrays can be the integer, byte, double, string\r
+    types or structures. (This excludes format characters <tt>BA</tt>).  Fixed-length\r
+    arrays can also be multi-dimensional like <tt>i##</tt>. Variable-length arrays can\r
+    have simple or complex elements-- for example, an array of ints <tt>A(i)</tt>, an\r
+    array of int/double pairs <tt>A(if)</tt>, or even nested arrays like <tt>A(A(if))</tt>.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p>Before explaining all the concepts, it&#8217;s illustrative to see how both kinds of\r
+arrays are used. Let&#8217;s pack the integers 0 through 9 both ways.</p></div>\r
+<div class="listingblock" id="fixed_pack">\r
+<div class="title">Packing 0-9 as a fixed-length array</div>\r
+<div class="content">\r
+<pre><tt>#include "tpl.h"\r
+int main() {\r
+    tpl_node *tn;\r
+    int x[] = {0,1,2,3,4,5,6,7,8,9};\r
+\r
+    tn = tpl_map("i#", x, 10);\r
+    tpl_pack(tn,0);                         /* pack all 10 elements at once */\r
+    tpl_dump(tn, TPL_FILE, "/tmp/fixed.tpl");\r
+    tpl_free(tn);\r
+}</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Note that the length of the fixed-length array (10) was passed as an argument to\r
+<tt>tpl_map()</tt>.  The corresponding unpacking <a href="#fixed_unpack">example</a> is listed\r
+further below. Now let&#8217;s see how we would pack 0-9 as a variable-length array:</p></div>\r
+<div class="listingblock">\r
+<div class="title">Packing 0-9 as a variable-length array</div>\r
+<div class="content">\r
+<pre><tt>#include "tpl.h"\r
+int main() {\r
+    tpl_node *tn;\r
+    int x;\r
+\r
+    tn = tpl_map("A(i)", &amp;x);\r
+    for(x = 0; x &lt; 10; x++) tpl_pack(tn,1);  /* pack one element at a time */\r
+    tpl_dump(tn, TPL_FILE, "/tmp/variable.tpl");\r
+    tpl_free(tn);\r
+}</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Notice how we called <tt>tpl_pack</tt> in a loop, once for each element 0-9. Again,\r
+there is a corresponding unpacking <a href="#var_unpack">example</a> shown later in the\r
+guide. You might also notice that this time, we passed 1 as the final argument\r
+to tpl_pack. This is an index number designating which variable-length array\r
+we&#8217;re packing. In this case, there is only one.</p></div>\r
+<h4 id="index">Index numbers</h4>\r
+<div class="paragraph"><p>Index numbers identify a particular variable-length array in the format string.\r
+Each <tt>A(&#8230;)</tt> in a format string has its own index number.  The index numbers\r
+are assigned left-to-right starting from 1. Examples:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>A(i)        /* index number 1 */\r
+A(i)A(i)    /* index numbers 1 and 2 */\r
+A(A(i))     /* index numbers 1 and 2 (order is independent of nesting) */</tt></pre>\r
+</div></div>\r
+<h5 id="_special_index_number_0">Special index number 0</h5>\r
+<div class="paragraph"><p>The special index number 0 designates all the format characters that are not\r
+inside an <tt>A(&#8230;)</tt>.  Examples of what index 0 does (and does not) designate:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>S(ius)      /* index 0 designates the whole thing */\r
+iA(c)u      /* index 0 designates the i and the u */\r
+c#A(i)S(ci) /* index 0 designates the c# and the S(ci) */</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>An index number is passed to <tt>tpl_pack</tt> and <tt>tpl_unpack</tt> to specify which\r
+variable-length array (or non-array, in the case of index number 0) to act upon.</p></div>\r
+<h3 id="_integers">Integers</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The array examples <a href="#fixed_pack">above</a> demonstrated how integers could be\r
+packed.  We&#8217;ll show some further examples here of unpacking integers and dealing\r
+with multi-dimensional arrays. The same program could be used to demonstrate\r
+working with byte, 16-bit shorts, 32-bit or 64-bit signed and unsigned integers\r
+with only a change to the data type and the format character.</p></div>\r
+<div class="listingblock" id="fixed_unpack">\r
+<div class="title">Unpacking 0-9 from a fixed-length array</div>\r
+<div class="content">\r
+<pre><tt>#include "tpl.h"\r
+int main() {\r
+    tpl_node *tn;\r
+    int x[10];\r
+\r
+    tn = tpl_map("i#", x, 10);\r
+    tpl_load(tn, TPL_FILE, "/tmp/fixed.tpl");\r
+    tpl_unpack(tn,0);  /* unpack all 10 elements at once */\r
+    tpl_free(tn);\r
+    /* now do something with x[0]...x[9].. (not shown */\r
+}</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>For completeness, let&#8217;s also see how to unpack a variable-length integer array.</p></div>\r
+<div class="listingblock" id="var_unpack">\r
+<div class="title">Unpacking 0-9 from a variable-length array</div>\r
+<div class="content">\r
+<pre><tt>#include "tpl.h"\r
+int main() {\r
+    tpl_node *tn;\r
+    int x;\r
+\r
+    tn = tpl_map("A(i)", &amp;x);\r
+    tpl_load(tn, TPL_FILE, "/tmp/variable.tpl");\r
+    while (tpl_unpack(tn,1) &gt; 0) printf("%d\n",x); /* unpack one by one */\r
+    tpl_free(tn);\r
+}</tt></pre>\r
+</div></div>\r
+<h4 id="multidim_int">Multi-dimensional arrays</h4>\r
+<div class="paragraph"><p>A multi-dimensional matrix of integers can be packed and unpacked the same way\r
+as any fixed-length array.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>int xy[XDIM][YDIM];\r
+...\r
+tn = tpl_map("i##", xy, XDIM, YDIM);\r
+tpl_pack(tn, 0);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>This single call to <tt>tpl_pack</tt> packs the entire matrix.</p></div>\r
+<h3 id="_strings">Strings</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Tpl can serialize C strings. A different format is used for <tt>char*</tt> vs. <tt>char[ ]</tt>\r
+as described below. Let&#8217;s look at <tt>char*</tt> first:</p></div>\r
+<div class="listingblock">\r
+<div class="title">Packing a string</div>\r
+<div class="content">\r
+<pre><tt>    #include "tpl.h"\r
+\r
+    int main() {\r
+        tpl_node *tn;\r
+        char *s = "hello, world!";\r
+        tn = tpl_map("s", &amp;s);\r
+        tpl_pack(tn,0);  /* copies "hello, world!" into the tpl */\r
+        tpl_dump(tn,TPL_FILE,"string.tpl");\r
+        tpl_free(tn);\r
+    }</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The <tt>char*</tt> must point to a null-terminated string or be a <tt>NULL</tt> pointer.</p></div>\r
+<div class="paragraph"><p>When deserializing (unpacking) a C string, space for it will be allocated\r
+automatically, but you are responsible for freeing it (unless it is <tt>NULL</tt>):</p></div>\r
+<div class="listingblock">\r
+<div class="title">Unpacking a string</div>\r
+<div class="content">\r
+<pre><tt>    #include "tpl.h"\r
+\r
+    int main() {\r
+        tpl_node *tn;\r
+        char *s;\r
+        tn = tpl_map("s", &amp;s);\r
+        tpl_load(tn,TPL_FILE,"string.tpl");\r
+        tpl_unpack(tn,0);   /* allocates space, points s to "hello, world!" */\r
+        printf("unpacked %s\n", s);\r
+        free(s);            /* our responsibility to free s */\r
+        tpl_free(tn);\r
+    }</tt></pre>\r
+</div></div>\r
+<h4 id="_char_vs_char">char* vs char[ ]</h4>\r
+<div class="paragraph"><p>The <tt>s</tt> format character is only for use with <tt>char*</tt> types. In the example\r
+above, <tt>s</tt> is a <tt>char*</tt>. If it had been a <tt>char s[14]</tt>, we would use the format\r
+characters <tt>c#</tt> to pack or unpack it, as a fixed-length character array. (This\r
+unpacks the characters "in-place", instead of into a dynamically allocated\r
+buffer). Also, a fixed-length buffer described by <tt>c#</tt> need not be\r
+null-terminated.</p></div>\r
+<h4 id="_arrays_of_strings">Arrays of strings</h4>\r
+<div class="paragraph"><p>You can use fixed- or variable-length arrays of strings in tpl. An example of\r
+packing a fixed-length two-dimensional array of strings is shown here.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>char *labels[2][3] = { {"one", "two", "three"},\r
+                       {"eins", "zwei", "drei" } };\r
+tpl_node *tn;\r
+tn = tpl_map("s##", labels, 2, 3);\r
+tpl_pack(tn,0);\r
+tpl_dump(tn,TPL_FILE,filename);\r
+tpl_free(tn);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Later, when unpacking these strings, the programmer must remember to free them\r
+one by one, after they are no longer needed.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>char *olabels[2][3];\r
+int i,j;</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tn = tpl_map("s##", olabels, 2, 3);\r
+tpl_load(tn,TPL_FILE,filename);\r
+tpl_unpack(tn,0);\r
+tpl_free(tn);</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>for(i=0;i&lt;2;i++) {\r
+  for(j=0;j&lt;3;j++) {\r
+    printf("%s\n", olabels[i][j]);\r
+    free(olabels[i][j]);\r
+  }\r
+}</tt></pre>\r
+</div></div>\r
+<h3 id="_binary_buffers">Binary buffers</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Packing an arbitrary-length binary buffer (tpl format character <tt>B</tt>) makes use\r
+of the <tt>tpl_bin</tt> structure.  You must declare this structure and populate it\r
+with the address and length of the binary buffer to be packed.</p></div>\r
+<div class="listingblock">\r
+<div class="title">Packing a binary buffer</div>\r
+<div class="content">\r
+<pre><tt>    #include "tpl.h"\r
+    #include &lt;sys/time.h&gt;\r
+\r
+    int main() {\r
+        tpl_node *tn;\r
+        tpl_bin tb;\r
+\r
+        /* we'll use a timeval as our guinea pig */\r
+        struct timeval tv;\r
+        gettimeofday(&amp;tv,NULL);\r
+\r
+        tn = tpl_map( "B", &amp;tb );\r
+        tb.sz = sizeof(struct timeval);  /* size of buffer to pack */\r
+        tb.addr = &amp;tv;                   /* address of buffer to pack */\r
+        tpl_pack( tn, 0 );\r
+        tpl_dump(tn, TPL_FILE, "bin.tpl");\r
+        tpl_free(tn);\r
+    }</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>When you unpack a binary buffer, tpl will automatically allocate it, and will\r
+populate your <tt>tpl_bin</tt> structure with its address and length. You are\r
+responsible for eventually freeing the buffer.</p></div>\r
+<div class="listingblock">\r
+<div class="title">Unpacking a binary buffer</div>\r
+<div class="content">\r
+<pre><tt>    #include "tpl.h"\r
+\r
+    int main() {\r
+        tpl_node *tn;\r
+        tpl_bin tb;\r
+\r
+        tn = tpl_map( "B", &amp;tb );\r
+        tpl_load( tn, TPL_FILE, "bin.tpl" );\r
+        tpl_unpack( tn, 0 );\r
+        tpl_free(tn);\r
+\r
+        printf("binary buffer of length %d at address %p\n", tb.sz, tb.addr);\r
+        free(tb.addr);  /* our responsibility to free it */\r
+    }</tt></pre>\r
+</div></div>\r
+<h3 id="_structures">Structures</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>You can use tpl to pack and unpack structures, and arrays of structures.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>struct ci {\r
+    char c;\r
+    int i;\r
+};\r
+struct ci s = {'a', 1};</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tn = tpl_map("S(ci)", &amp;s);  /* pass structure address */\r
+tpl_pack(tn, 0);\r
+tpl_dump(tn, TPL_FILE, "struct.tpl");\r
+tpl_free(tn);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>As shown, omit the individual arguments for the format characters inside the\r
+parenthesis. The exception is for fixed-length arrays; when <tt>S(&#8230;)</tt> contains a\r
+<tt>#</tt> character, its length argument is required: <tt>tpl_map("S(f#i)", &amp;s, 10);</tt></p></div>\r
+<div class="paragraph"><p>When using the <tt>S(&#8230;)</tt> format, the only characters allowed inside the\r
+parentheses are <tt>iujvcsfIU#$()</tt>.</p></div>\r
+<h4 id="_structure_arrays">Structure arrays</h4>\r
+<div class="paragraph"><p>Arrays of structures are the same as simple arrays. Fixed- or variable- length\r
+arrays are supported.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>struct ci sa[100], one;</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tn = tpl_map("S(ci)#", sa, 100);  /* fixed-length array of 100 structures */\r
+tn = tpl_map("A(S(ci))", &amp;one);   /* variable-length array (one at a time)*/</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The differences between fixed- and variable-length arrays are explained in the\r
+<a href="#arrays">Arrays</a> section.</p></div>\r
+<h4 id="_nested_structures">Nested structures</h4>\r
+<div class="paragraph"><p>When dealing with nested structures, the outermost structure uses the <tt>S</tt> format\r
+character, and the inner nested structures use the <tt>$</tt> format. Only the\r
+<em>outermost</em> structure&#8217;s address is given to <tt>tpl_map</tt>.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>struct inner_t {\r
+  char a;\r
+}</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>struct outer_t {\r
+  char b;\r
+  struct inner_t i;\r
+}</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tpl_node *tn;\r
+struct outer_t outer = {'b', {'a'}};</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tn = tpl_map("S(c$(c))", &amp;outer);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Structures can nest to any level. Currently tpl does not support fixed-length\r
+array suffixes on inner structures.  However the outermost structure can have a\r
+length suffix even if it contains some nested structures.</p></div>\r
+<h3 id="_linked_lists">Linked lists</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>While tpl has no specific data type for a linked list, the technique for\r
+packing them is illustrated here.  First describe your list element as a\r
+format string and then surround it with <tt>A(&#8230;)</tt> to describe it as\r
+variable-length array.  Then, using a temporary variable, iterate over each\r
+list element, copying it to the temporary variable and packing it.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>struct element {\r
+  char c;\r
+  int i;\r
+  struct element *next;\r
+}</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>struct element *list, *i, tmp;\r
+tpl_node *tn;</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>/* add some elements to list.. (not shown)*/</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tn = tpl_map("A(ci)", &amp;tmp);\r
+for(i = list; i != NULL; i=i-&gt;next) {\r
+  tmp = *i;\r
+  tpl_pack(tn, 1);\r
+}\r
+tpl_dump(tn,TPL_FILE,"list.tpl");\r
+tpl_free(tn);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Unpacking is similar. The <tt>for</tt> loop is just replaced with:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>while( tpl_unpack(tn,1) &gt; 0) {\r
+  struct element *newelt = malloc(sizeof(struct element));\r
+  *newelt = tmp;\r
+  add_to_list(list, newelt);\r
+}</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>As you can see, tpl does not reinstate the whole list at once-- just one\r
+element at a time. You need to link the elements manually. A future release of\r
+tpl may support <em>pointer swizzling</em> to make this easier.</p></div>\r
+</div>\r
+<h2 id="_api">API</h2>\r
+<div class="sectionbody">\r
+<h3 id="tpl_map">tpl_map</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The only way to create a tpl is to call <tt>tpl_map()</tt>. The first argument is the\r
+<a href="#format">format string</a>. This is followed by a list of arguments as required by\r
+the particular characters in the format string. E.g,</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tpl_node *tn;\r
+int i;\r
+tn = tpl_map( "A(i)", &amp;i );</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The function creates a mapping between the items in the format string and the C\r
+program variables whose addresses are given. Later, the C variables will be read\r
+or written as the tpl is packed or unpacked.</p></div>\r
+<div class="paragraph"><p>This function returns a <tt>tpl_node*</tt> on success, or <tt>NULL</tt> on failure.</p></div>\r
+<h3 id="tpl_pack">tpl_pack</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The function <tt>tpl_pack()</tt> packs data into a tpl. The arguments to\r
+<tt>tpl_pack()</tt> are a <tt>tpl_node*</tt> and an <a href="#index">index number</a>.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tn = tpl_map("A(i)A(c)", &amp;i, &amp;c);\r
+for(i=0; i&lt;10; i++) tpl_pack(tn, 1);    /* pack 0-9 into index 1 */\r
+for(c='a; c&lt;='z'; c++) tpl_pack(tn, 2); /* pack a-z into index 2 */</tt></pre>\r
+</div></div>\r
+<div class="sidebarblock">\r
+<div class="sidebar-content">\r
+<div class="sidebar-title">Data is copied when packed</div>\r
+<div class="paragraph"><p>Every call to <tt>tpl_pack()</tt> immediately <em>copies</em> the data being packed. Thus\r
+the program is free to immediately overwrite or re-use the packed variables.</p></div>\r
+</div></div>\r
+<h4 id="_index_number_0">Index number 0</h4>\r
+<div class="paragraph"><p>It is necessary to pack index number 0 only if the format string contains\r
+characters that are not inside an <tt>A(&#8230;)</tt>, such as the <tt>i</tt> in the format string\r
+<tt>iA(c)</tt>.</p></div>\r
+<h4 id="_variable_length_arrays">Variable-length arrays</h4>\r
+<h5 id="_adding_elements_to_an_array">Adding elements to an array</h5>\r
+<div class="paragraph"><p>To add elements to a variable-length array, call <tt>tpl_pack()</tt> repeatedly.  Each\r
+call adds another element to the array.</p></div>\r
+<h5 id="_zero_length_arrays_are_ok">Zero-length arrays are ok</h5>\r
+<div class="paragraph"><p>It&#8217;s perfectly acceptable to pack nothing into a variable-length array,\r
+resulting in a zero-length array.</p></div>\r
+<h5 id="nested_pack">Packing nested arrays</h5>\r
+<div class="paragraph"><p>In a format string containing a nested, variable-length array, such as\r
+<tt>A(A(s))</tt>, the inner, child array should be packed prior to the parent array.</p></div>\r
+<div class="paragraph"><p>When you pack a parent array, a "snapshot" of the current child array is placed\r
+into the parent&#8217;s new element.  Packing a parent array also empties the child\r
+array. This way, you can pack new data into the child, then pack the parent\r
+again. This creates distinct parent elements which each contain distinct child\r
+arrays.</p></div>\r
+<div class="admonitionblock">\r
+<table><tr>\r
+<td class="icon">\r
+<div class="title">Tip</div>\r
+</td>\r
+<td class="content">When dealing with nested arrays like <tt>A(A(i))</tt>, <em>pack</em> them from the "inside\r
+out" (child first), but <em>unpack</em> them from the "outside in" (parent first).</td>\r
+</tr></table>\r
+</div>\r
+<div class="paragraph"><p>The example below creates a tpl having the format string <tt>A(A(c))</tt>.</p></div>\r
+<div class="listingblock">\r
+<div class="title">Packing nested arrays</div>\r
+<div class="content">\r
+<pre><tt>#include "tpl.h"\r
+\r
+int main() {\r
+    char c;\r
+    tpl_node *tn;\r
+\r
+    tn = tpl_map("A(A(c))", &amp;c);\r
+\r
+    for(c='a'; c&lt;'c'; c++) tpl_pack(tn,2);  /* pack child (twice) */\r
+    tpl_pack(tn, 1);                        /* pack parent */\r
+\r
+    for(c='1'; c&lt;'4'; c++) tpl_pack(tn,2);  /* pack child (three times) */\r
+    tpl_pack(tn, 1);                        /* pack parent */\r
+\r
+    tpl_dump(tn, TPL_FILE, "test40.tpl");\r
+    tpl_free(tn);\r
+}</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>This creates a nested array in which the parent has two elements: the first\r
+element is the two-element nested array <em>a</em>, <em>b</em>; and the second element is\r
+the three-element nested array <em>1</em>, <em>2</em>, <em>3</em>.\r
+The <a href="#nested_unpack">nested unpacking example</a> shows how this tpl is unpacked.</p></div>\r
+<h3 id="tpl_dump">tpl_dump</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>After packing a tpl, <tt>tpl_dump()</tt> is used to write the tpl image to a file,\r
+memory buffer or file descriptor. The corresponding modes are shown below. A\r
+final mode is for querying the output size without actually performing the dump.</p></div>\r
+<div class="tableblock">\r
+<table rules="none"\r
+width="80%"\r
+frame="border"\r
+cellspacing="0" cellpadding="4">\r
+<col width="30%" />\r
+<col width="70%" />\r
+<thead valign="top">\r
+<tr>\r
+<th align="center">Write to&#8230;      </th>\r
+<th align="left">Usage</th>\r
+</tr>\r
+</thead>\r
+<tbody valign="top">\r
+<tr>\r
+<td align="center"><p class="table">file</p></td>\r
+<td align="left"><p class="table"><tt>tpl_dump(tn, TPL_FILE, "file.tpl" );</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table">file descriptor</p></td>\r
+<td align="left"><p class="table"><tt>tpl_dump(tn, TPL_FD, 2);</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table">memory</p></td>\r
+<td align="left"><p class="table"><tt>tpl_dump(tn, TPL_MEM, &amp;addr, &amp;len );</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table">caller&#8217;s memory</p></td>\r
+<td align="left"><p class="table"><tt>tpl_dump(tn, TPL_MEM|TPL_PREALLOCD, buf, sizeof(buf));</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="center"><p class="table">just get size</p></td>\r
+<td align="left"><p class="table"><tt>tpl_dump(tn, TPL_GETSIZE, &amp;sz);</tt></p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<div class="paragraph"><p>The first argument is the <tt>tpl_node*</tt> and the second is one of these constants:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+<tt>TPL_FILE</tt>\r
+</dt>\r
+<dd>\r
+<p>\r
+    Writes the tpl to a file whose name is given in the following argument.\r
+    The file is created with permissions 664 (<tt>rw-rw-r--</tt>) unless further\r
+    restricted by the process <tt>umask</tt>.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<tt>TPL_FD</tt>\r
+</dt>\r
+<dd>\r
+<p>\r
+    Writes the tpl to the file descriptor given in the following argument.\r
+    The descriptor can be either blocking or non-blocking, but will busy-loop\r
+    if non-blocking and the contents cannot be written immediately.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<tt>TPL_MEM</tt>\r
+</dt>\r
+<dd>\r
+<p>\r
+    Writes the tpl to a memory buffer. The following two arguments must be a\r
+    <tt>void**</tt> and a <tt>size_t*</tt>. The function will allocate a buffer and store\r
+    its address and length into these locations.  The caller is responsible to\r
+    <tt>free()</tt> the buffer when done using it.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<tt>TPL_MEM|TPL_PREALLOCD</tt>\r
+</dt>\r
+<dd>\r
+<p>\r
+    Writes the tpl to a memory buffer that the caller has already allocated or\r
+    declared. The following two arguments must be a <tt>void*</tt> and a <tt>size_t</tt>\r
+    specifying the buffer address and size respectively. (If the buffer is of\r
+    insufficient size to receive the tpl dump, the function will return -1).\r
+    This mode can be useful in conjunction with <tt>tpl_load</tt> in <tt>TPL_EXCESS_OK</tt>\r
+    mode, as shown <a href="#excess_ok">here.</a>\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<tt>TPL_GETSIZE</tt>\r
+</dt>\r
+<dd>\r
+<p>\r
+    This special mode does not actually dump the tpl. Instead it places the size\r
+    that the dump <em>would</em> require into the <tt>uint32_t</tt> pointed to by the\r
+    following argument.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p>The return value is 0 on success, or -1 on error.</p></div>\r
+<div class="paragraph"><p>The <tt>tpl_dump()</tt> function does not free the tpl.  Use <tt>tpl_free()</tt> to release\r
+the tpl&#8217;s resources when done.</p></div>\r
+<div class="admonitionblock">\r
+<table><tr>\r
+<td class="icon">\r
+<div class="title">Tip</div>\r
+</td>\r
+<td class="content">\r
+<div class="title">Back-to-back tpl images require no delimiter</div>If you want to store a series of tpl images, or transmit sequential tpl images\r
+over a socket (perhaps as messages to another program), you can simply dump them\r
+sequentially without needing to add any delimiter for the individual tpl images.\r
+Tpl images are internally delimited, so <tt>tpl_load</tt> will read just one at a time\r
+even if multiple images are contiguous.</td>\r
+</tr></table>\r
+</div>\r
+<h3 id="tpl_load">tpl_load</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This API function reads a previously-dumped tpl image from a file, memory\r
+buffer or file descriptor, and prepares it for subsequent unpacking.  The format\r
+string specified in the preceding call to <tt>tpl_map()</tt> will be cross-checked\r
+for equality with the format string stored in the tpl image.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tn = tpl_map( "A(i)", &amp;i );\r
+tpl_load( tn, TPL_FILE, "demo.tpl" );</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The first argument to <tt>tpl_load()</tt> is the <tt>tpl_node*</tt>.  The second argument is\r
+one of the constants:</p></div>\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+<tt>TPL_FILE</tt>\r
+</dt>\r
+<dd>\r
+<p>\r
+    Loads the tpl from the file named in the following argument. It is also\r
+    possible to bitwise-OR this flag with <tt>TPL_EXCESS_OK</tt> as explained below.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<tt>TPL_MEM</tt>\r
+</dt>\r
+<dd>\r
+<p>\r
+    Loads the tpl from a memory buffer. The following two arguments must be a\r
+    <tt>void*</tt> and a <tt>size_t</tt>, specifying the buffer address and size,\r
+    respectively.  The caller must not free the memory buffer until after\r
+    freeing the tpl with <tt>tpl_free()</tt>. (If the caller wishes to hand over\r
+    responsibility for freeing the memory buffer, so that it&#8217;s automatically\r
+    freed along with the tpl when <tt>tpl_free()</tt> is called, the constant\r
+    <tt>TPL_UFREE</tt> may be bitwise-OR&#8217;d with <tt>TPL_MEM</tt> to achieve this).\r
+    Furthermore, <tt>TPL_MEM</tt> may be bitwise-OR&#8217;d with <tt>TPL_EXCESS_OK</tt>, explained\r
+    below.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<tt>TPL_FD</tt>\r
+</dt>\r
+<dd>\r
+<p>\r
+    Loads the tpl from the file descriptor given in the following argument.\r
+    The descriptor is read until one complete tpl image is loaded; no bytes\r
+    past the end of the tpl image will be read.  The descriptor can be either\r
+    blocking or non-blocking, but will busy-loop if non-blocking and the\r
+    contents cannot be read immediately.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+<div class="paragraph"><p>During loading, the tpl image will be extensively checked for internal validity.</p></div>\r
+<div class="paragraph"><p>This function returns 0 on success or -1 on error.</p></div>\r
+<h4 id="excess_ok"><tt>TPL_EXCESS_OK</tt></h4>\r
+<div class="paragraph"><p>When reading a tpl image from a file or memory (but not from a file descriptor)\r
+the size of the file or memory buffer must exactly equal that of the tpl image\r
+stored therein. In other words, no excess trailing data beyond the tpl image is\r
+permitted. The bit flag <tt>TPL_EXCESS_OK</tt> can be OR&#8217;d with <tt>TPL_MEM</tt> or <tt>TPL_FILE</tt>\r
+to relax this requirement.</p></div>\r
+<div class="paragraph"><p>A situation where this flag can be useful is in conjunction with <tt>tpl_dump</tt> in\r
+the <tt>TPL_MEM|TPL_PREALLOCD</tt> mode. In this example, the program does not concern\r
+itself with the actual tpl size as long as <tt>LEN</tt> is sufficiently large.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>char buf[LEN];  /* will store and read tpl images here */\r
+...\r
+tpl_dump(tn, TPL_MEM|TPL_PREALLOCD, buf, LEN);\r
+...\r
+tpl_load(tn, TPL_MEM|TPL_EXCESS_OK, buf, LEN);</tt></pre>\r
+</div></div>\r
+<h3 id="tpl_unpack">tpl_unpack</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The <tt>tpl_unpack()</tt> function unpacks data from the tpl. When data is unpacked,\r
+it is copied to the C program variables originally specified in <tt>tpl_map()</tt>.\r
+The first argument to <tt>tpl_unpack</tt> is the <tt>tpl_node*</tt> for the tpl and the\r
+second argument is an <a href="#index">index number</a>.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tn = tpl_map( "A(i)A(c)", &amp;i, &amp;c );\r
+tpl_load( tn, TPL_FILE, "nested.tpl" );\r
+while (tpl_unpack( tn, 1) &gt; 0) printf("i is %d\n", i); /* unpack index 1 */\r
+while (tpl_unpack( tn, 2) &gt; 0) printf("c is %c\n", c); /* unpack index 2 */</tt></pre>\r
+</div></div>\r
+<h4 id="_index_number_0_2">Index number 0</h4>\r
+<div class="paragraph"><p>It is necessary to unpack index number 0 only if the format string contains\r
+characters that are not inside an <tt>A(&#8230;)</tt>, such as the <tt>i</tt> in the format string\r
+<tt>iA(c)</tt>.</p></div>\r
+<h4 id="_variable_length_arrays_2">Variable-length arrays</h4>\r
+<h5 id="_unpacking_elements_from_an_array">Unpacking elements from an array</h5>\r
+<div class="paragraph"><p>For variable-length arrays, each call to <tt>tpl_unpack()</tt> unpacks another element.\r
+The return value can be used to tell when you&#8217;re done: if it&#8217;s positive, an\r
+element was unpacked; if it&#8217;s 0, nothing was unpacked because there are no more\r
+elements. A negative retun value indicates an error (e.g. invalid index number).\r
+In this document, we usually unpack variable-length arrays using a <tt>while</tt> loop:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>while( tpl_unpack( tn, 1 ) &gt; 0 ) {\r
+    /* got another element */\r
+}</tt></pre>\r
+</div></div>\r
+<h5 id="_array_length">Array length</h5>\r
+<div class="paragraph"><p>When unpacking a variable-length array, it may be convenient to know ahead of\r
+time how many elements will need to be unpacked.  You can use <tt>tpl_Alen()</tt> to\r
+get this number.</p></div>\r
+<h5 id="nested_unpack">Unpacking nested arrays</h5>\r
+<div class="paragraph"><p>In a format string containing a nested variable-length array such as <tt>A(A(s))</tt>,\r
+unpack the outer, parent array before unpacking the child array.</p></div>\r
+<div class="paragraph"><p>When you unpack a parent array, it prepares the child array for unpacking.\r
+After unpacking the elements of the child array, the program can repeat the\r
+process by unpacking another parent element, then the child elements, and so on.\r
+The example below unpacks a tpl having the format string <tt>A(A(c))</tt>.</p></div>\r
+<div class="listingblock">\r
+<div class="title">Unpacking nested arrays</div>\r
+<div class="content">\r
+<pre><tt>#include "tpl.h"\r
+#include &lt;stdio.h&gt;\r
+\r
+int main() {\r
+    char c;\r
+    tpl_node *tn;\r
+\r
+    tn = tpl_map("A(A(c))", &amp;c);\r
+\r
+    tpl_load(tn, TPL_FILE, "test40.tpl");\r
+    while (tpl_unpack(tn,1) &gt; 0) {\r
+        while (tpl_unpack(tn,2) &gt; 0) printf("%c ",c);\r
+        printf("\n");\r
+    }\r
+    tpl_free(tn);\r
+}</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The file <tt>test40.tpl</tt> is from the <a href="#nested_pack">nested packing example</a>. When\r
+run, this program prints:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>a b\r
+1 2 3</tt></pre>\r
+</div></div>\r
+<h3 id="tpl_free">tpl_free</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>The final step for any tpl is to release it using <tt>tpl_free()</tt>. Its only\r
+argument is the the <tt>tpl_node*</tt> to free.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tpl_free( tn );</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>This function does not return a value (it is <tt>void</tt>).</p></div>\r
+<h3 id="tpl_alen">tpl_Alen</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This function takes a <tt>tpl_node*</tt> and an index number and returns an <tt>int</tt>\r
+specifying the number of elements in the variable-length array.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>num_elements = tpl_Alen(tn, index);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>This is mainly useful for programs that unpack data and need to know ahead of\r
+time the number of elements that will need to be unpacked. (It returns the\r
+current number of elements; it will decrease as elements are unpacked).</p></div>\r
+<h3 id="tpl_peek">tpl_peek</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This function peeks into a file or a memory buffer containing a tpl image and\r
+and returns a copy of its format string.  It can also peek at the lengths of\r
+any fixed-length arrays in the format string, or it can also peek into the data\r
+stored in the tpl.</p></div>\r
+<h4 id="_format_peek">Format peek</h4>\r
+<div class="paragraph"><p>The format string can be obtained\r
+like this:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>fmt = tpl_peek(TPL_FILE, "file.tpl");\r
+fmt = tpl_peek(TPL_MEM, addr, sz);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>On success, a copy of the format string is returned. The caller must eventually\r
+free it. On error, such as a non-existent file, or an invalid tpl image, it\r
+returns <tt>NULL</tt>.</p></div>\r
+<h4 id="_array_length_peek">Array length peek</h4>\r
+<div class="paragraph"><p>The lengths of all fixed-length arrays in the format string can be queried using\r
+the <tt>TPL_FXLENS</tt> mode. It provides the number of such fixed-length arrays and\r
+their lengths. If the former is non-zero, the caller must free the latter array\r
+when finished. The format string itself must also be freed.</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>uint32_t num_fxlens, *fxlens, j;\r
+fmt = tpl_peek(TPL_FILE|TPL_FXLENS, filename, &amp;num_fxlens, &amp;fxlens);\r
+if (fmt) {\r
+  printf("format %s, num_fxlens %u\n", fmt, num_fxlens);\r
+  for(j=0; j&lt;num_fxlens; j++) printf("fxlens[%u] %u\n", j, fxlens[j]);\r
+  if (num_fxlens &gt; 0) free(fxlens);\r
+  free(fmt);\r
+}</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The <tt>TPL_FXLENS</tt> mode is mutually exclusive with <tt>TPL_DATAPEEK</tt>.</p></div>\r
+<h4 id="_data_peek">Data peek</h4>\r
+<div class="paragraph"><p>To peek into the data, additional arguments are used. This is a quick\r
+alternative to mapping, loading and unpacking the tpl, but peeking is limited\r
+to the data in index 0. In other words, no peeking into <tt>A(&#8230;)</tt> types.\r
+Suppose the tpl image in <tt>file.tpl</tt> has the format string <tt>siA(i)</tt>. Then the\r
+index 0 format characters are <tt>si</tt>. This is how to peek at their content:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>char *s;\r
+int i;\r
+fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "file.tpl", "si", &amp;s, &amp;i);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>Now <tt>s</tt>, <tt>i</tt>, and <tt>fmt</tt> have been populated with data.  The caller must\r
+eventually free <tt>fmt</tt> and <tt>s</tt> because they are allocated strings.\r
+Of course, it works with <tt>TPL_MEM</tt> as well as <tt>TPL_FILE</tt>.  Notice that\r
+<tt>TPL_DATAPEEK</tt> was OR&#8217;d with the mode. You can also specify <em>any leading\r
+portion</em> of the index 0 format if you don&#8217;t want to peek at the whole thing:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "file.tpl", "s", &amp;s);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The <tt>TPL_DATAPEEK</tt> mode is mutually exclusive with <tt>TPL_FXLENS</tt>.</p></div>\r
+<h5 id="_structure_peek">Structure peek</h5>\r
+<div class="paragraph"><p>Lastly you can peek into <tt>S(&#8230;)</tt> structures in index 0, but omit the\r
+surrounding <tt>S(&#8230;)</tt> in the format, and specify an argument to receive\r
+each structure member individually. You can specify any leading portion\r
+of the structure format. For example if <tt>struct.tpl</tt> has the format string\r
+<tt>S(si)</tt>, you can peek at its data in these ways:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "struct.tpl", "s", &amp;s);\r
+fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "struct.tpl", "si", &amp;s, &amp;i);</tt></pre>\r
+</div></div>\r
+<h3 id="tpl_jot">tpl_jot</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>This is a quick shortcut for generating a tpl. It can be used instead of the\r
+usual "map, pack, dump, and free" lifecycle. With <tt>tpl_jot</tt> all those steps are\r
+handled for you.  It only works for simple formats-- namely, those without\r
+<tt>A(&#8230;)</tt> in their format string. Here is how it is used:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>char *hello = "hello", *world = "world";\r
+tpl_jot( TPL_FILE, "file.tpl", "ss", &amp;hello, &amp;world);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>It supports the three standard modes, <tt>TPL_FILE</tt>, <tt>TPL_FD</tt> and <tt>TPL_MEM</tt>.\r
+It returns -1 on failure (such as a bad format string or error writing the\r
+file) or 0 on success.</p></div>\r
+<h3 id="hooks">tpl_hook</h3><div style="clear:left"></div>\r
+<div class="paragraph"><p>Most users will just leave these hooks at their default values. You can change\r
+these hook values if you want to modify tpl&#8217;s internal memory management and\r
+error reporting behavior.</p></div>\r
+<div class="paragraph"><p>A global structure called <tt>tpl_hook</tt> encapsulates the hooks.  A program can\r
+reconfigure any hook by specifying an alternative function whose prototype\r
+matches the default. For example:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>#include "tpl.h"\r
+extern tpl_hook_t tpl_hook;</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>int main() {\r
+    tpl_hook.oops = printf;\r
+    ...\r
+}</tt></pre>\r
+</div></div>\r
+<div class="tableblock">\r
+<table rules="none"\r
+width="90%"\r
+frame="border"\r
+cellspacing="0" cellpadding="4">\r
+<caption class="title">Configurable hooks</caption>\r
+<col width="33%" />\r
+<col width="33%" />\r
+<col width="33%" />\r
+<thead valign="top">\r
+<tr>\r
+<th align="left">Hook                </th>\r
+<th align="left">Description                  </th>\r
+<th align="left"> Default</th>\r
+</tr>\r
+</thead>\r
+<tbody valign="top">\r
+<tr>\r
+<td align="left"><p class="table"><tt>tpl_hook.oops</tt></p></td>\r
+<td align="left"><p class="table">log error messages</p></td>\r
+<td align="left"><p class="table"><tt>tpl_oops</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="left"><p class="table"><tt>tpl_hook.malloc</tt></p></td>\r
+<td align="left"><p class="table">allocate memory</p></td>\r
+<td align="left"><p class="table"><tt>malloc</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="left"><p class="table"><tt>tpl_hook.realloc</tt></p></td>\r
+<td align="left"><p class="table">reallocate memory</p></td>\r
+<td align="left"><p class="table"><tt>realloc</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="left"><p class="table"><tt>tpl_hook.free</tt></p></td>\r
+<td align="left"><p class="table">free memory</p></td>\r
+<td align="left"><p class="table"><tt>free</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="left"><p class="table"><tt>tpl_hook.fatal</tt></p></td>\r
+<td align="left"><p class="table">log fatal message and exit</p></td>\r
+<td align="left"><p class="table"><tt>tpl_fatal</tt></p></td>\r
+</tr>\r
+<tr>\r
+<td align="left"><p class="table"><tt>tpl_hook.gather_max</tt></p></td>\r
+<td align="left"><p class="table">tpl_gather max image size</p></td>\r
+<td align="left"><p class="table"><tt>0 (unlimited)</tt></p></td>\r
+</tr>\r
+</tbody>\r
+</table>\r
+</div>\r
+<h4 id="_the_oops_hook">The oops hook</h4>\r
+<div class="paragraph"><p>The <tt>oops</tt> has the same prototype as <tt>printf</tt>. The built-in default oops\r
+handling function writes the error message to <tt>stderr</tt>.</p></div>\r
+<h4 id="_the_fatal_hook">The fatal hook</h4>\r
+<div class="paragraph"><p>The fatal hook is invoked when a tpl function cannot continue because of an out-\r
+of-memory condition or some other usage violation or inconsistency. It has this\r
+prototype:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>void fatal_fcn(char *fmt, ...);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The <tt>fatal</tt> hook must not return. It must either exit, <em>or</em> if the program needs\r
+to handle the failure and keep executing, <tt>setjmp</tt> and <tt>longjmp</tt> can be used.\r
+The default behavior is to <tt>exit(-1)</tt>.</p></div>\r
+<div class="listingblock">\r
+<div class="title">Using longjmp in a fatal error handler</div>\r
+<div class="content">\r
+<pre><tt>#include &lt;setjmp.h&gt;\r
+#include &lt;stdio.h&gt;\r
+#include &lt;stdarg.h&gt;\r
+#include "tpl.h"\r
+\r
+jmp_buf env;\r
+extern tpl_hook_t tpl_hook;\r
+\r
+void catch_fatal(char *fmt, ...) {\r
+  va_list ap;\r
+\r
+  va_start(ap, fmt);\r
+  vfprintf(stderr, fmt, ap);\r
+  va_end(ap);\r
+  longjmp(env,-1);                /* return to setjmp point */\r
+}\r
+\r
+int main() {\r
+  int err;\r
+  tpl_node *tn;\r
+  tpl_hook.fatal = catch_fatal;    /* install fatal handler */\r
+\r
+  err = setjmp(env); /* on error, control will return here  */\r
+  if (err) {\r
+    printf("caught error!\n");\r
+    return -1;\r
+  }\r
+\r
+  tn = tpl_map("@");              /* generate a fatal error */\r
+  printf("program ending, without error\n");\r
+  return 0;\r
+}</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>This example is included in <tt>tests/test123.c</tt>. When run, this program prints:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>unsupported option @\r
+failed to parse @\r
+caught error!</tt></pre>\r
+</div></div>\r
+<h3 id="_tpl_gather">tpl_gather</h3><div style="clear:left"></div>\r
+<div class="sidebarblock">\r
+<div class="sidebar-content">\r
+<div class="sidebar-title">Most programs don&#8217;t need this</div>\r
+<div class="paragraph"><p>Normally, <tt>tpl_load()</tt> is used to read a tpl image having an expected format\r
+string.  A more generic operation is to acquire a tpl image whose format string is\r
+unknown. E.g., a generic message-receiving function might gather tpl images of\r
+varying format and route them to their final destination. This is the purpose of\r
+<tt>tpl_gather</tt>. It produces a memory buffer containing one tpl image. If there\r
+are multiple contiguous images in the input, it gathers exactly one image at a\r
+time.</p></div>\r
+</div></div>\r
+<div class="paragraph"><p>The prototype for this function is:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>int tpl_gather( int mode, ...);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The <tt>mode</tt> argument is one of three constants listed below, which must be\r
+followed by the mode-specific required arguments:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>TPL_GATHER_BLOCKING,    int fd, void **img, size_t *sz\r
+TPL_GATHER_NONBLOCKING, int fd, tpl_gather_t **gs, tpl_gather_cb *cb, void *data\r
+TPL_GATHER_MEM,         void *addr, size_t sz, tpl_gather_t **gs, tpl_gather_cb *cb, void *data</tt></pre>\r
+</div></div>\r
+<div class="admonitionblock">\r
+<table><tr>\r
+<td class="icon">\r
+<div class="title">Note</div>\r
+</td>\r
+<td class="content">\r
+<div class="title"><tt>tpl_hook.gather_max</tt></div>All modes honor <tt>tpl_hook.gather_max</tt>, specifying the maximum byte size for a\r
+tpl image to be gathered (the default is unlimited, signified by 0). If a source\r
+attempts to send a tpl image larger than this maximum, whatever partial image\r
+has been read will be discarded, and no further reading will take place; in this\r
+case <tt>tpl_gather</tt> will return a negative (error) value to inform the caller that\r
+it should stop gathering from this source, and close the originating file\r
+descriptor if there is one. (The whole idea is to prevent untrusted sources from\r
+sending extremely large tpl images which would consume too much memory.)</td>\r
+</tr></table>\r
+</div>\r
+<h4 id="_tt_tpl_gather_blocking_tt"><tt>TPL_GATHER_BLOCKING</tt></h4>\r
+<div class="paragraph"><p>In this mode, <tt>tpl_gather</tt> blocks while reading file descriptor <tt>fd</tt> until one\r
+complete tpl image is read. No bytes past the end of the tpl image will be read.\r
+The address of the buffer containing the image is returned in <tt>img</tt> and its size\r
+is placed in <tt>sz</tt>. The caller is responsible for eventually freeing the buffer.\r
+The function returns 1 on success, 0 on end-of-file, or a negative number on\r
+error.</p></div>\r
+<h4 id="_tt_tpl_gather_nonblocking_tt"><tt>TPL_GATHER_NONBLOCKING</tt></h4>\r
+<div class="paragraph"><p>This mode is for non-blocking, event-driven programs that implement their\r
+own file descriptor readability testing using <tt>select()</tt> or the like. In this\r
+mode, tpl images are gathered in chunks as data becomes readable. Whenever a\r
+full tpl image has been gathered, it invokes a caller-specified callback to do\r
+something with the image.  The arguments are the file descriptor <tt>fd</tt> which the\r
+caller has determined to be readable and which must be in non-blocking mode, a\r
+pointer to a file-descriptor-specific handle which the caller has declared\r
+(explained below); a callback to invoke when a tpl image has been read; and an\r
+opaque pointer that will passed to the callback.</p></div>\r
+<div class="paragraph"><p>For each file descriptor on which <tt>tpl_gather</tt> will be used, the caller must\r
+declare a <tt>tpl_gather_t*</tt> and initialize it to <tt>NULL</tt>. Thereafter it will be\r
+used internally by <tt>tpl_gather</tt> whenever data is readable on the descriptor.</p></div>\r
+<div class="paragraph"><p>The callback will only be invoked whenever <tt>tpl_gather()</tt> has accumulated one\r
+complete tpl image. It must have this prototype:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>int (tpl_gather_cb)(void *img, size_t sz, void *data);</tt></pre>\r
+</div></div>\r
+<div class="paragraph"><p>The callback can do anything with the tpl image but it must not free it. It can\r
+be copied if it needs to survive past the callback&#8217;s return. The callback should\r
+return 0 under normal circumstances, or a negative number to abort; that is,\r
+returning a negative number causes <tt>tpl_gather</tt> itself to discard any remaining\r
+full or partial tpl images that have been read, and to return a negative number\r
+(-4 in particular) to signal its caller to close the file descriptor.</p></div>\r
+<div class="paragraph"><p>The return value of <tt>tpl_gather()</tt> is negative if an error occured or 0 if a\r
+normal EOF was encountered-- both cases require that the caller close the file\r
+descriptor (and stop monitoring it for readability, obviously). If the return\r
+value is positive, the function succeeded in gathering whatever data was\r
+currently readable, which may have been a partial tpl image, or one or more\r
+complete images.</p></div>\r
+<h5 id="_typical_usage">Typical Usage</h5>\r
+<div class="paragraph"><p>The program will have established a file descriptor in non-blocking mode and\r
+be monitoring it for readability, using <tt>select()</tt>. Whenever it&#8217;s readable, the\r
+program calls <tt>tpl_gather()</tt>. In skeletal terms:</p></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>tpl_gather_t *gt=NULL;\r
+int rc;</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>void fd_is_readable(int fd) {\r
+  rc = tpl_gather( TPL_GATHER_NONBLOCKING, fd, &amp;gt, callback, NULL );\r
+  if (rc &lt;= 0) {\r
+      close(fd);               /* got eof or fatal */\r
+      stop_watching_fd(fd);\r
+  }\r
+}</tt></pre>\r
+</div></div>\r
+<div class="literalblock">\r
+<div class="content">\r
+<pre><tt>int callback( void *img, size_t sz, void *data ) {\r
+  printf("got a tpl image\n"); /* do something with img. do not free it. */\r
+  return 0;                    /* normal (no error) */\r
+}</tt></pre>\r
+</div></div>\r
+<h4 id="_tt_tpl_gather_mem_tt"><tt>TPL_GATHER_MEM</tt></h4>\r
+<div class="paragraph"><p>This mode is identical to <tt>TPL_GATHER_NONBLOCKING</tt> except that it gathers from a\r
+memory buffer instead of from a file descriptor. In other words, if some other\r
+layer of code-- say, a decryption function (that is decrypting fixed-size\r
+blocks) produces tpl fragments one-by-one, this mode can be used to reconstitute\r
+the tpl images and invoke the callback for each one. Its parameters are the same\r
+as for the <tt>TPL_GATHER_NONBLOCKING</tt> mode except that instead of a file\r
+descriptor, it takes a buffer address and size. The return values are also the\r
+same as for <tt>TPL_GATHER_NONBLOCKING</tt> noting of course there is no file\r
+descriptor to close on a non-positive return value.</p></div>\r
+</div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Version 1.5<br />\r
+Last updated 2010-02-05 04:37:37 EDT\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/libs/libtpl-1.5/doc/pdf/userguide.pdf b/libs/libtpl-1.5/doc/pdf/userguide.pdf
new file mode 100755 (executable)
index 0000000..b870fdc
Binary files /dev/null and b/libs/libtpl-1.5/doc/pdf/userguide.pdf differ
diff --git a/libs/libtpl-1.5/doc/txt/ChangeLog.txt b/libs/libtpl-1.5/doc/txt/ChangeLog.txt
new file mode 100755 (executable)
index 0000000..b55964d
--- /dev/null
@@ -0,0 +1,59 @@
+tpl ChangeLog
+=============
+
+Version 1.5 (2010-02-05)
+--------------------------
+* tpl now builds as a DLL under Microsoft Visual Studio! (thanks, degski and Zhang Yafei!)
+* there are now two download options: the http://downloads.sourceforge.net/tpl/libtpl-1.5.tar.bz2[tarball] and the Visual Studio http://downloads.sourceforge.net/tpl/tpl-1.5-vs2008.zip[solution] 
+* a crash in `tpl_free` on certain format strings has been fixed (thanks, Eric Rose!)
+* fixed a bug in `tpl_dump` on 64-bit, big-endian platforms
+* changed some pointer casts from `long` to `uintptr_t` since 64-bit Windows has 32-bit longs
+* tpl has been downloaded 4,195 times.
+
+
+Version 1.4 (2009-04-21)
+--------------------------
+* fixed-length arrays can now be multi-dimensional like `i##`
+* fixed-length string arrays like `s#` are now supported
+* nested structures can now be expressed, using the dollar symbol, e.g. `S(ci$(cc))`
+* `tpl_dump` can use a caller-allocated output buffer (`TPL_MEM|TPL_PREALLOCD`)
+* `tpl_load` can tolerate excess space in input buffer (`TPL_MEM|TPL_EXCESS_OK`)
+* implement `TPL_FXLENS` flag for `tpl_peek` to get lengths of fixed-length arrays
+* implement `TPL_GETSIZE` flag for `tpl_dump` to get dump size without dumping
+* fix success return code from `tpl_dump(TPL_FD,...)` (thanks, Max Lapan!)
+* deprecated the wildcard unpacking `S(*)` feature
+
+Version 1.3 (2009-02-10)
+--------------------------
+* added `TPL_DATAPEEK` mode for `tpl_peek`
+* added support for `NULL` strings
+* added support for 16-bit integer types (`j`,`v`)
+* added `tpl_jot`
+* added support for fixed-length arrays of structures `S(...)#`
+* added support for pre-C99 compilers (thanks, Wei Wei!)
+* improved structure alignment calculation (thanks, Wu Yongwei!)
+* added RPM spec file (thanks, Alessandro Ren!)
+* compiles cleanly with `-Wall` and `-pedantic` and with `-O3`
+* made link:license.html[BSD license] terms even more permissive
+* test suite: exit with status zero when all tests pass
+* added PDF user guide 
+* added http://troydhanson.wordpress.com/feed/[update news] image:img/rss.png[(RSS)]
+* added http://apps.sourceforge.net/mediawiki/tpl/[tpl wiki]
+
+Version 1.2 (2007-04-27)
+--------------------------
+* Perl API and XML converter support 64-bit types
+
+Version 1.1 (2007-04-25)
+--------------------------
+* support for serializing C structures
+* support for serializing fixed-length arrays 
+* MinGW support (thanks, Horea Haitonic!)
+* revised User Guide
+
+Version 1.0 (2006-09-28)
+--------------------------
+* Initial version
+
+// vim: set tw=80 wm=2 nowrap syntax=asciidoc:
+
diff --git a/libs/libtpl-1.5/doc/txt/compiling.txt b/libs/libtpl-1.5/doc/txt/compiling.txt
new file mode 100755 (executable)
index 0000000..abb73ec
--- /dev/null
@@ -0,0 +1,38 @@
+Compiling libtpl.a and libtpl.so
+--------------------------------
+
+********************************************************************************
+Normally in the top-level directory you simply run:
+
+    ./configure
+    make
+    make install
+
+The rest of the document is not needed if you use this method.
+********************************************************************************
+
+
+Manual compilation of static and shared library on a GNU Linux system:
+----------------------------------------------------------------------
+
+First cd into the "src" directory.
+
+Static library
+~~~~~~~~~~~~~~
+You can build the static library `libtpl.a` using these commands:
+
+    cc -c tpl.c
+    ar rc libtpl.a tpl.o
+    ranlib libtpl.a
+
+Dynamic library
+~~~~~~~~~~~~~~
+You can build the dynamic library `libtpl.so` using these commands:
+
+    cc -fpic -c tpl.c
+    cc -shared -o libtpl.so tpl.o
+
+Keep in mind that you need to set the `LD_LIBRARY_PATH` environment variable
+to include the directory where `libtpl.so` is installed in order for your
+program to run. Alternatively you can put `libtpl.so` in a standard place like
+`/usr/lib` and regenerate `ld.so.cache` using `ldconfig`.
diff --git a/libs/libtpl-1.5/doc/txt/examples.txt b/libs/libtpl-1.5/doc/txt/examples.txt
new file mode 100755 (executable)
index 0000000..9faca3f
--- /dev/null
@@ -0,0 +1,297 @@
+tpl examples
+============
+Troy D. Hanson <troydhanson@comcast.net>>
+v1.0, October 2006
+
+include::sflogo.txt[]
+include::topnav.txt[]
+
+Examples
+--------
+include::toc.txt[]
+
+This document is a set of representative examples demonstrating how to use
+tpl. If you're looking for a more explanatory document, please read the
+link:userguide.html[User Guide].
+
+An integer array
+~~~~~~~~~~~~~~~~
+
+.Storing an array of integers to file
+-------------------------------------------------------------------------------
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map( "A(i)", &i );
+    for( i=0; i<10; i++ ) {
+        tpl_pack( tn, 1 );  
+    }
+    tpl_dump( tn, TPL_FILE, "demo.tpl" );
+    tpl_free( tn );
+}
+-------------------------------------------------------------------------------
+
+A program that unpacks this tpl data file is shown below.
+
+.Re-reading an array of integers from file
+-------------------------------------------------------------------------------
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map( "A(i)", &i );
+    tpl_load( tn, TPL_FILE, "demo.tpl" );
+    while (tpl_unpack( tn, 1 ) > 0) {
+        printf("%d ", i);
+    }
+    tpl_free( tn );
+}
+-------------------------------------------------------------------------------
+
+When run, this program prints:
+
+    0 1 2 3 4 5 6 7 8 9 
+
+
+A nested array
+~~~~~~~~~~~~~~
+
+.Packing nested arrays
+--------------------------------------------------------------------------------
+#include "tpl.h"
+
+int main() {
+    char c;
+    tpl_node *tn;
+
+    tn = tpl_map("A(A(c))", &c);
+
+    for(c='a'; c<'c'; c++) tpl_pack(tn,2);
+    tpl_pack(tn, 1);
+
+    for(c='1'; c<'4'; c++) tpl_pack(tn,2);
+    tpl_pack(tn, 1);
+
+    tpl_dump(tn, TPL_FILE, "test40.tpl");
+    tpl_free(tn);
+}
+--------------------------------------------------------------------------------
+
+This creates a nested array in which the parent has two elements: the first
+element is the two-element nested array 'a', 'b'; and the second element is
+the three-element nested array '1', '2', '3'. 
+
+.Unpacking nested arrays
+--------------------------------------------------------------------------------
+#include "tpl.h"
+#include <stdio.h>
+
+int main() {
+    char c;
+    tpl_node *tn;
+
+    tn = tpl_map("A(A(c))", &c);
+
+    tpl_load(tn, TPL_FILE, "test40.tpl");
+    while (tpl_unpack(tn,1) > 0) {
+        while (tpl_unpack(tn,2) > 0) printf("%c ",c);
+        printf("\n");
+    }
+    tpl_free(tn);
+}
+--------------------------------------------------------------------------------
+
+
+When run, this program prints:
+
+    a b 
+    1 2 3 
+
+A string array
+~~~~~~~~~~~~~~
+
+.Packing a string array
+-------------------------------------------------------------------------------
+    #include "tpl.h"
+
+    int main() {
+        tpl_node *tn;
+        char *s;
+
+        tn = tpl_map( "A(s)", &s );
+
+        s = "bob";
+        tpl_pack(tn, 1);
+
+        s = "betty";
+        tpl_pack(tn, 1);
+
+        tpl_dump(tn, TPL_FILE, "strings.tpl");
+        tpl_free(tn);
+    }
+-------------------------------------------------------------------------------
+
+.Unpacking a string array
+-------------------------------------------------------------------------------
+    #include <stdio.h>
+    #include "tpl.h"
+
+    int main() {
+        tpl_node *tn;
+        char *s;
+
+        tn = tpl_map( "A(s)", &s );
+        tpl_load( tn, TPL_FILE, "strings.tpl" );
+
+        while (tpl_unpack( tn, 1 ) > 0) {
+            printf("%s\n", s);
+            free(s);  /* important! */
+        }
+
+        tpl_free(tn);
+    }
+-------------------------------------------------------------------------------
+
+When run, this program prints:
+
+    bob
+    betty
+
+Integer/string pairs
+~~~~~~~~~~~~~~~~~~~~
+
+.Packing integer/string pairs
+-------------------------------------------------------------------------------
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    int id;
+    char *name, *names[] = { "joe", "bob", "mary" };
+
+    tn = tpl_map("A(is)", &id, &name);
+
+    for(id=0,name=names[id]; id < 3; name=names[++id])
+        tpl_pack(tn,1);
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test35.tpl");
+    tpl_free(tn);
+}
+-------------------------------------------------------------------------------
+
+.Unpacking integer/string pairs
+-------------------------------------------------------------------------------
+#include <stdio.h>
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    int id;
+    char *name;
+
+    tn = tpl_map("A(is)", &id, &name);
+    tpl_load(tn, TPL_FILE, "/tmp/test35.tpl");
+
+    while ( tpl_unpack(tn,1) > 0 )
+        printf("id %d, user %s\n", id, name);
+
+    tpl_free(tn);
+}
+-------------------------------------------------------------------------------
+
+When run, this program prints:
+
+    id 0, user joe
+    id 1, user bob
+    id 2, user mary
+
+A binary buffer
+~~~~~~~~~~~~~~~
+
+.Packing a binary buffer
+-------------------------------------------------------------------------------
+    #include "tpl.h"
+    #include <sys/time.h>
+
+    int main() {
+        tpl_node *tn;
+        tpl_bin tb;
+        struct timeval tv;       /* we'll pack this structure as raw binary */
+        gettimeofday(&tv,NULL);  /* populate the structure with some data */
+
+        tn = tpl_map( "B", &tb );
+        tb.sz = sizeof(struct timeval);
+        tb.addr = &tv;
+        tpl_pack( tn, 0 );
+
+        tpl_dump(tn, TPL_FILE, "bin.tpl");
+        tpl_free(tn);
+    }
+-------------------------------------------------------------------------------
+
+
+.Unpacking a binary buffer
+-------------------------------------------------------------------------------
+    #include "tpl.h"
+
+    int main() {
+        tpl_node *tn;
+        tpl_bin tb;
+
+        tn = tpl_map( "B", &tb );
+        tpl_load( tn, TPL_FILE, "bin.tpl" );
+
+        tpl_unpack( tn, 0 );
+        printf("binary buffer of length %d at address %p\n", tb.sz, tb.addr);
+        free(tb.addr);  /* important! */
+
+        tpl_free(tn);
+    }
+-------------------------------------------------------------------------------
+
+
+Simple pipe IPC 
+~~~~~~~~~~~~~~~
+
+This is a simple example of inter-process communication (IPC) over a pipe.
+
+.IPC over a pipe
+-------------------------------------------------------------------------------
+int main() {
+    tpl_node *tn;
+    unsigned i, sum=0;
+    int fd[2], pid;
+
+    pipe(fd);
+    if ( (pid = fork()) == 0) {   /* child */
+
+        tn = tpl_map("A(u)",&i);
+        tpl_load(tn, TPL_FD, fd[0]);
+        while (tpl_unpack(tn,1) > 0) sum += i;
+        tpl_free(tn);
+        printf("sum is %d\n", sum);
+
+    } else if (pid > 0) {         /* parent */
+
+        tn = tpl_map("A(u)",&i);
+        for(i=0;i<10000;i++) tpl_pack(tn,1);
+        tpl_dump(tn,TPL_FD, fd[1] );
+        tpl_free(tn);
+
+        waitpid(pid,NULL,0);
+    } 
+}
+-------------------------------------------------------------------------------
+
+The child unpacks the integers in the message, and sums them, printing:
+
+    49995000
+
+The example above (with `#include` headers omitted here) is included in the
+file `tests/test28.c`.
diff --git a/libs/libtpl-1.5/doc/txt/future.txt b/libs/libtpl-1.5/doc/txt/future.txt
new file mode 100755 (executable)
index 0000000..dc2240f
--- /dev/null
@@ -0,0 +1,52 @@
+For future reference these are some API design ideas- not working code!
+
+--------------------------------------------------------------------------------
+Java API ideas
+--------------------------------------------------------------------------------
+http://www.ioplex.com/~miallen/encdec/  (binary pack/unpack utilities)
+
+The Java API would take an object, and a list of field  names, then use the
+Java Reflection API to read or write those fields  during packing and
+unpacking.
+
+I.e. if you are going to unpack a tpl with format string A(if), you  
+might create a Java class that has two instance variables (an int and  
+a double). Then you create an object of that class, and pass it to  
+tpl_map (or perhaps a constructor for the Tpl class), like
+
+class Unpacker {
+        int count;
+        double weight;
+}
+... 
+Unpacker up = new Unpacker();
+Tpl tn = new Tpl("A(if)", up, "count", "weight");
+tn.tpl_unpack(1);  // stores unpacked values into count,weight using Reflection
+
+--------------------------------------------------------------------------------
+Ruby API ideas
+--------------------------------------------------------------------------------
+#!/usr/local/ruby/bin/ruby -w
+
+class Tpl < Hash
+       def initialize(fmt, *args)
+         @fmt = fmt
+         @args = args
+       end
+
+       def pack
+         @args.each {|key| puts "#{key} #{self[key]}"}
+       end
+end
+
+
+p = Tpl.new("A(i)", :id);
+10.times do |i|
+   p[:id] = i
+   p.pack
+end
+p.dump("/tmp/file.tpl")  # p.dump(arg) checks arg.respond_to?(:write)
+
+p = Tpl.new("A(i)", :id);
+p.load("/tmp/file.tpl")
+p.unpack(1) {|h| puts h[:id]}
diff --git a/libs/libtpl-1.5/doc/txt/perl.txt b/libs/libtpl-1.5/doc/txt/perl.txt
new file mode 100755 (executable)
index 0000000..5c66843
--- /dev/null
@@ -0,0 +1,302 @@
+tpl Perl API
+============
+Troy D. Hanson <troydhanson@comcast.net>
+v1.1, April 2007
+
+include::sflogo.txt[]
+include::topnav.txt[]
+
+Perl API
+--------
+include::toc.txt[]
+
+The Perl API for reading and writing tpl is nearly identical to the C API. This
+document will briefly explain the Perl API and provide examples. The chief
+motivation for having a Perl API is to communicate with C programs that use tpl.
+
+[TIP]
+.Start with the C API
+This document assumes familiarity with the C API.  The concepts of using tpl
+are not explained here. For an introduction to tpl and its C API, see the
+link:userguide.html[User Guide]. 
+
+Tpl.pm
+~~~~~~
+The `Tpl.pm` file (in the `lang/perl`) directory contains the Perl module.  You
+can copy it to another directory if you wish. Your Perl program may need to
+include a `use lib` statement to find the module.
+
+    #!/usr/bin/perl
+    use lib "/some/directory";
+    use Tpl;
+
+tpl_map
+~~~~~~~
+This function resembles the C version, except that it's invoked via the `Tpl`
+module, and it takes references to Perl variables after the format string.
+
+    my $i;
+    my $tpl = Tpl->tpl_map("A(i)",\$i);
+
+The return value is a tpl object; all other API calls are object methods.
+Incidentally, there is no `tpl_free()` method corresponding to the C API.  
+
+Fixed-length arrays
+^^^^^^^^^^^^^^^^^^^
+Format strings such as `i#` denote a fixed-length array. In the Perl API,
+fixed-length arrays require two arguments: a list reference, and the fixed
+length. For example:
+
+    my @x;
+    my $tpl = Tpl->tpl_map("i#", \@x, 10);
+
+When fixed-length arrays are packed or unpacked, the specified number of
+elements will be copied from (or placed into) the designated list.
+
+Structures
+^^^^^^^^^^
+Format strings containing `S(...)` are handled in the Perl API as if only the
+interior, parenthesized part was present. (It does not work like the C API). So
+simply ignore the `S(...)` and consider only its interior format characters when
+constructing the argument list:
+    
+    my ($str, $int);
+    my $tpl = Tpl->tpl_map("S(si)", \$str, \$int);
+
+It really only makes sense to use `S(...)` in a format string in the Perl API if
+you are communicating with a C program that uses structures. 
+
+tpl_pack
+~~~~~~~~
+This is nearly identical to the C version. The only argument is the index
+number to pack.
+
+    $tpl->tpl_pack(1);
+
+tpl_dump
+~~~~~~~~
+This method is a little different than the C version. Given no arguments, it
+returns the tpl image; given one argument it writes a file with that name.
+
+    $tpl->tpl_dump("demo.tpl");   # writes demo.tpl
+
+Or,
+
+    my $img = $tpl->tpl_dump();   
+
+The tpl image is a binary buffer. You can do whatever you want with it, such as
+write it to a socket or pipe (probably to C program listening on the other end),
+or save it somewhere and later re-load it using `tpl_load()`.
+
+tpl_load
+~~~~~~~~
+This method loads a tpl image from a file or from a Perl variable.  It takes
+one argument. If it's not a reference, it's assumed to be a filename to load.
+
+    $tpl->tpl_load("demo.tpl");
+
+Otherwise, if the argument is a Perl reference, it's construed as a variable
+containing the tpl image:
+
+    $tpl->tpl_load(\$img);
+
+The method will `die` if the image is invalid or the file doesn't exist. You
+can wrap it with `eval` to catch such errors:
+
+    eval { $tpl->tpl_load(\$img); };
+    print "failed to load\n" if $@;
+
+tpl_unpack
+~~~~~~~~~~
+This is nearly identical to the C version. The only argument is the index
+number to unpack.
+
+    $tpl->tpl_unpack(1);
+
+Examples
+--------
+
+Integer array
+~~~~~~~~~~~~~
+
+.Packing A(i) to file
+--------------------------------------------------------------------------------
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Tpl;
+
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+for($i=0; $i<10; $i++) { 
+    $tpl->tpl_pack(1); 
+}
+$tpl->tpl_dump("demo.tpl");
+--------------------------------------------------------------------------------
+
+.Unpacking A(i) from file
+--------------------------------------------------------------------------------
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Tpl;
+
+my $j;
+my $tpl2 = Tpl->tpl_map("A(i)",\$j);
+$tpl2->tpl_load("demo.tpl");
+while($tpl2->tpl_unpack(1) > 0) { 
+    print "$j\n";
+}
+--------------------------------------------------------------------------------
+
+Message-passing
+~~~~~~~~~~~~~~~
+While the bulk of this example is socket handling, it demonstrates how you can
+use tpl as a message-passing format. In the real-world, you might have a C
+server and a Perl client, for example. In this example, we'll code both a client
+and a server in Perl.
+
+.A server that sums integers
+********************************************************************************
+Programming literature is rife with contrived examples so we will follow in that
+tradition. Our server will do no more than sum a list of integers. But in doing
+so it will demonstrate message passing adequately. Both its input (the integer
+array) and its output (an integer) are tpl images, passed over a TCP/IP socket.
+********************************************************************************
+
+Server
+^^^^^^
+The server waits for a connection from a client. When it gets one, it accepts
+the connection and immediately forks a child process to handle it. Then it goes
+back to waiting for another new connection.
+
+The server child process handles the client by loading and unpacking the tpl
+image sent by the client (containing an array of integers). It calculates their
+sum and constructs a new tpl image containing the sum, which it sends back to
+the client.
+
+.Server
+--------------------------------------------------------------------------------
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use IO::Socket::INET;
+use Tpl;
+
+$SIG{CHLD} = "IGNORE"; # don't create zombies
+
+our $port = 2000;
+
+sub handle_client {
+    my $client = shift;
+
+    undef $/;
+    my $request = <$client>; # get request (slurp) 
+
+    # read input array, and calculate total
+    my ($i,$total);
+    my $tpl = Tpl->tpl_map("A(i)", \$i);
+    eval { $tpl->tpl_load(\$request); };
+    die "received invalid tpl" if $@;
+    $total += $i while $tpl->tpl_unpack(1) > 0;
+
+    # formulate response and send
+    my $tpl2 = Tpl->tpl_map("i", \$total);
+    $tpl2->tpl_pack(0);
+    my $response = $tpl2->tpl_dump();
+    print $client $response;
+    close $client;
+}
+
+my $server = IO::Socket::INET->new(LocalPort => $port,
+                   Type => SOCK_STREAM,
+                   Reuse => 1,
+                   Listen => 10 )
+        or die "Can't listen on port $port: $!\n";
+
+while (1) {
+    my $client = $server->accept();
+    next unless $client;
+    # new connection
+    my $pid = fork;
+    die "can't fork: $!\n" unless defined $pid;
+    if ($pid > 0) {
+        # parent
+        close $client;
+    } elsif ($pid == 0) {
+        # child
+        handle_client($client);
+        exit(0);
+    }
+}
+close ($server);
+--------------------------------------------------------------------------------
+
+Client
+^^^^^^
+
+The client is a simpler program. It constructs the tpl image containing the
+integer array (taken from its command-line arguments), connects to the server
+and sends the tpl image to it, and then awaits the response tpl. The response
+containing the sum is loaded, unpacked and printed.
+
+.Client
+--------------------------------------------------------------------------------
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use IO::Socket::INET;
+use Tpl;
+
+our $port = 2000;
+
+# construct tpl
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+$tpl->tpl_pack(1) while ($i=shift @ARGV);
+my $request = $tpl->tpl_dump();
+
+# send to server, get response
+my $socket = IO::Socket::INET->new("localhost:$port") or die "can't connect";
+print $socket $request;
+shutdown($socket,1);       # done writing (half-close)
+undef $/;
+my $response = <$socket>;      # get reply (slurp)
+
+# decode response (or print error)
+my $total;
+my $tpl2 = Tpl->tpl_map("i", \$total);
+eval { $tpl2->tpl_load(\$response); };
+die "invalid response\n" if $@;
+$tpl2->tpl_unpack(0);
+print "total is $total\n";
+--------------------------------------------------------------------------------
+
+Running thise example
+^^^^^^^^^^^^^^^^^^^^^
+If the client and server programs are in `client.pl` and `server.pl`, then
+you can run the example by starting the server in one window:
+
+        ./server.pl
+
+Then run the client in another window. E.g.,
+
+        ./client.pl 1 2 3 4 5
+
+The client runs and then exits, printing:
+
+        total is 15
+
+You can re-run the client with different arguments. When done, type `Ctrl-C` in
+the server window to terminate it.
+
+// vim: set tw=80 wm=2 syntax=asciidoc: 
+
diff --git a/libs/libtpl-1.5/doc/txt/sflogo.txt b/libs/libtpl-1.5/doc/txt/sflogo.txt
new file mode 100755 (executable)
index 0000000..68b153b
--- /dev/null
@@ -0,0 +1,5 @@
+ifdef::backend-xhtml11[]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+<a style="float: right;" href="http://sourceforge.net/projects/tpl"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=157637&amp;type=16" width="150" height="40" alt="SourceForge.net" /></a>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+endif::backend-xhtml11[]
diff --git a/libs/libtpl-1.5/doc/txt/toc.txt b/libs/libtpl-1.5/doc/txt/toc.txt
new file mode 100755 (executable)
index 0000000..458eed1
--- /dev/null
@@ -0,0 +1,85 @@
+ifdef::backend-xhtml11[]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+<div id="toc"></div>
+<script>
+window.onload=generate_TOC
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+
+function H_getText(el) {
+  var text = "";
+  for (var i = el.firstChild; i != null; i = i.nextSibling) {
+    if (i.nodeType == 3 /* Node.TEXT_NODE, IE doesn't speak constants */)
+      text += i.data;
+    else if (i.firstChild != null)
+      text += H_getText(i);
+  }
+  return text;
+}
+
+function TOC_EL(el, text, level) {
+  this.element = el;
+  this.text = text;
+  this.level = level;
+}
+
+function getHeadlines(el) {
+  var l = new Array;
+  var rx = /[hH]([2-3])/;
+  // internal recursive function that scans the DOM tree
+  var rec = function (el) {
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {
+      if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+        if (rx.exec(i.tagName))
+          l[l.length] = new TOC_EL(i, H_getText(i), parseInt(RegExp.$1));
+        rec(i);
+      }
+    }
+  }
+  rec(el);
+  return l;
+}
+
+function generate_TOC() {
+  var parent = document.getElementById("toc"); 
+  var toc_hdr = document.createElement("div");
+  var toc_hdr_txt = document.createTextNode("CONTENTS");
+  toc_hdr.appendChild(toc_hdr_txt);
+  /* toc_hdr.setAttribute("id","hdr"); */
+  toc_hdr.id = "hdr";
+  parent.appendChild(toc_hdr);
+  var hs = getHeadlines(document.getElementsByTagName("body")[0]);
+  for (var i = 0; i < hs.length; ++i) {
+    var hi = hs[i];
+    var d = document.createElement("div");
+    if (hi.element.id == "") hi.element.id = "gen" + i;
+    var a = document.createElement("a");
+    a.href = "#" + hi.element.id;
+    a.appendChild(document.createTextNode(hi.text));
+    d.appendChild(a);
+    d.className = "level" + hi.level;
+    parent.appendChild(d);
+    /*
+    if (hi.level == 3) {
+        var dvtop = document.createElement("div");
+        dvtop.className = "toplink";
+        dvtop.appendChild(document.createTextNode("^top^"));
+        dvtop.onclick=function(){scrollTo(0,0);};
+        hi.element.appendChild(dvtop);
+    }
+    */
+  }
+}
+</script>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+endif::backend-xhtml11[]
diff --git a/libs/libtpl-1.5/doc/txt/topnav.txt b/libs/libtpl-1.5/doc/txt/topnav.txt
new file mode 100755 (executable)
index 0000000..257e665
--- /dev/null
@@ -0,0 +1,10 @@
+ifdef::backend-xhtml11[]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  <div id="topnav" style="font-size: 9pt; font-family: sans-serif;">
+  <a style="padding: 8px;" href="http://sourceforge.net/projects/tpl/">sf.net summary page</a> &gt;
+  <a style="padding: 8px;" href="index.html">tpl home</a> &gt;
+  {doctitle}
+  <a style="padding: 8px;" href="userguide.pdf">[View PDF]</a> 
+  </div>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+endif::backend-xhtml11[]
diff --git a/libs/libtpl-1.5/doc/txt/userguide.txt b/libs/libtpl-1.5/doc/txt/userguide.txt
new file mode 100755 (executable)
index 0000000..705fe3b
--- /dev/null
@@ -0,0 +1,1264 @@
+tpl User Guide
+==============
+Troy D. Hanson <thanson@users.sourceforge.net>
+v1.5, February 2010
+
+include::sflogo.txt[]
+include::topnav.txt[]
+
+Overview
+--------
+include::toc.txt[]
+
+Serialization in C
+~~~~~~~~~~~~~~~~~~
+Tpl is a library for serializing C data. The data is stored in its natural
+binary form. The API is small and tries to stay "out of the way". 
+Tpl can serialize many C data types, including structures.
+
+Uses for tpl
+~~~~~~~~~~~~
+Tpl makes a convenient file format. For example, suppose a program needs to
+store a list of user names and ids. This can be expressed using the format
+string `A(si)`.  If the program needs two such lists (say, one for regular
+users and one for administrators) this could be expressed as `A(si)A(si)`. It
+is easy to read and write this kind of structured data using tpl.
+
+Tpl can also be used as an IPC message format. It handles byte order issues
+and deframing individual messages off of a stream automatically.
+
+Expressing type
+~~~~~~~~~~~~~~~
+The "data type" of a tpl is explicitly stated as a format string. There is
+never any ambiguity about the type of data stored in a tpl.  Some examples:
+
+* `A(is)` is a variable-length array of integer-string pairs
+* `A(is)A(is)` are two such arrays, completely independent of one another
+* `S(ci)` is a structure containing a char and integer
+* `S(ci)#` is a fixed-length array of the latter structure
+* `A(A(i))` is a nested array, that is, an array of integer arrays
+
+The tpl image
+~~~~~~~~~~~~~
+A tpl image is the serialized form of a tpl, stored in a memory buffer or file,
+or written to a file descriptor.
+
+What's in a tpl image?
+^^^^^^^^^^^^^^^^^^^^^^
+There is no need to understand the internal structure of the tpl image. But for the
+curious, the image is a strictly defined binary buffer having two sections, 
+a header and the data.  The header encodes the length of the image, its
+format string, endian order and other flags. The data section contains the
+packed data. 
+
+No framing needed
+^^^^^^^^^^^^^^^^^
+A property of the tpl image is that consecutive images can be written to a stream
+without requiring any delimiter between them. The reader making use of 
+`tpl_gather` (or `tpl_load` in `TPL_FD` mode) will obtain exactly one tpl image at 
+a time.  Therefore tpl images can be used as an IPC message format without any
+higher-level framing protocol. 
+
+Data portability
+^^^^^^^^^^^^^^^^
+A tpl image generated on one kind of CPU will generally be portable to other
+CPU types when tpl is used properly. This may be a surprise considering that 
+tpl is a binary format. But tpl has been carefully designed to make this work.
+Each <<types,format character>> has an associated explicitly-sized type. For 
+integer and floating point types, whose "endian" or byte-order convention varies
+from one CPU to another, tpl automatically and transparently corrects the
+endian order (if needed) during the unpacking process.  Floating point numbers
+present their own <<trouble_with_double,special difficulties>>. 'No guarantees
+are made with regard to floating point portability.' That said, because many
+modern CPU's use IEEE 754 floating point representation, data is likely to be
+portable among them. 
+
+XML and Perl
+~~~~~~~~~~~~
+'Note: The `tplxml` utility and the Perl module are currently unsupported in tpl 1.5.'
+
+XML
+^^^
+While a tpl image is a binary entity, you can view any tpl image in XML format
+using the included `tplxml` utility, located in the `lang/perl` directory. 
+
+    tplxml file.tpl > file.xml
+    tplxml file.xml > file.tpl
+
+The utility is bidirectional, as shown.  The file extension is not important;
+`tplxml` inspects its input to see if it's tpl or XML. You can also pipe data
+into it instead of giving it a filename. The `tplxml` utility is slow. Its
+purpose is two-fold: debugging (manual inspection of the data in a tpl), and
+interoperability with XML-based programs.  The resulting XML is often ten times
+the size of the original binary tpl image.
+
+Perl 
+^^^^
+There is a Perl module in `lang/perl/Tpl.pm`. The link:perl.html[Perl API] 
+is convenient for writing Perl scripts that interoperate with C programs, and
+need to pass structured data back and forth. It is written in pure Perl. 
+
+Platforms
+~~~~~~~~~
+The tpl software was developed for POSIX systems and has been tested on 32- and 64-bit
+platforms including:
+
+ * Linux 
+ * Solaris 
+ * Mac OS X 
+ * OpenBSD 
+ * Windows using Visual Studio 2008 or 2010, or Cygwin or MinGW
+
+BSD licensed
+~~~~~~~~~~~~
+This software is made available under the 
+link:license.html[revised BSD license]. 
+It is free and open source. 
+
+Download
+~~~~~~~~
+Please follow the link to download on the 
+http://tpl.sourceforge.net[tpl website].
+
+Getting help
+~~~~~~~~~~~~
+If you need help, you are welcome to email the author at
+mailto:thanson@users.sourceforge.net[].
+
+Resources
+~~~~~~~~~
+News::
+ The author has a news feed for http://troydhanson.wordpress.com/feed/[software updates] image:img/rss.png[(RSS)].
+
+Build and install
+-----------------
+
+Tpl has no dependencies on libraries other than the system C library. You
+can simply copy the tpl source into your project, so you have no dependencies.
+Alternatively, you can build tpl as a library and link it to your program.
+
+As source
+~~~~~~~~~
+The simplest way to use tpl is to copy the source files `tpl.h` and `tpl.c`
+(from the `src/` directory) right into your project, and build them with the
+rest of your source files. No special compiler flags are required. 
+
+As a library
+~~~~~~~~~~~~
+Alternatively, to build tpl as a library, from the top-level directory, run:
+
+    ./configure
+    make
+    make install
+
+This installs a static library `libtpl.a` and a shared library (e.g.,
+`libtpl.so`), if your system supports them, in standard places. The installation
+directory can be customized using `./configure --prefix=/some/directory`. Run
+`configure --help` for further options.
+
+Test suite
+^^^^^^^^^^
+You can compile and run the built-in test suite by running:
+    
+    cd tests/
+    make
+
+On Windows
+~~~~~~~~~~
+
+DLL
+^^^
+On the tpl home page, a Visual Studio 2008 solution package is available for
+download.  This zip file contains pre-built 32- and 64-bit versions of tpl as a
+DLL.  If you like, you can build the DLL yourself using  VS2008 or VS2010 (the
+free Express Edition is sufficient) by opening the solution file and choosing
+Build Solution. 
+
+Non-DLL usage
+^^^^^^^^^^^^^
+Alternatively, tpl can be used directly (instead of as a DLL) by compiling
+the tpl sources right into your program. To do this, add `tpl.c`, `tpl.h`,
+`win/mman.h` and `win/mmap.c` to your program's source and header files and 
+add the preprocessor definition `TPL_NOLIB`.
+
+MinGW/Cygwin
+^^^^^^^^^^^^
+Prior to tpl release 1.5, using tpl on Windows required building it with MinGW
+or Cygwin. This is no longer necessary. If you want to build it that way anyway,
+use the non-Windows (i.e. tar.bz2) tpl download and follow the "configure; make;
+make install" approach.
+
+API concepts
+------------
+To use tpl, you need to know the order in which to call the API functions, and
+the background concepts of format string, arrays and index numbers.
+
+Order of functions
+~~~~~~~~~~~~~~~~~~
+Creating a tpl is always the first step, and freeing it is the last step. In
+between, you either pack and dump the tpl (if you're serializing data) or you
+load a tpl image and unpack it (if you're deserializing data).
+
+.Order of usage 
+[width="50%",cols="^1,^5m,^5m",grid="none",options="header"]
+|===============================================================================
+|Step  |     If you're serializing...|      If you're deserializing...
+| 1.   |     tpl_map()               |      tpl_map()      
+| 2.   |     tpl_pack()              |      tpl_load()  
+| 3.   |     tpl_dump()              |      tpl_unpack()
+| 4.   |     tpl_free()              |      tpl_free()       
+|===============================================================================
+
+[[format]]
+Format string
+~~~~~~~~~~~~~
+When a tpl is created using `tpl_map()`, its data type is expressed as a format
+string.  Each character in the format string has an associated argument of a 
+specific type.  For example, this is how a format string and its arguments are
+passed in to `tpl_map`:
+
+    tpl_node *tn;
+    char c;
+    int i[10];
+    tn = tpl_map("ci#", &c, i, 10);  /* ci# is our format string */
+
+[[types]]
+.Supported format characters
+[width="90%",grid="none",options="header",cols="5^m,20,20"]
+|================================================================================
+|Type |  Description                                             | Required argument type 
+| j   |  16-bit signed int                                       | int16_t* or equivalent
+| v   |  16-bit unsigned int                                     | uint16_t* or equivalent
+| i   |  32-bit signed int                                       | int32_t* or equivalent
+| u   |  32-bit unsigned int                                     | uint32_t* or equivalent
+| I   |  64-bit signed int                                       | int64_t* or equivalent
+| U   |  64-bit unsigned int                                     | uint64_t* or equivalent
+| c   |  character (byte)                                        | char*   
+| s   |  string                                                  | char**
+| f   |  64-bit double precision float                           | double* (varies by platform)
+| #   |  array length; modifies preceding `iujvIUcsf` or `S(...)`| int                        
+| B   |  binary buffer (arbitrary-length)                        | tpl_bin*
+| S   |  structure (...)                                         | struct *
+| $   |  nested structure (...)                                  | none    
+| A   |  array (...)                                             | none    
+|================================================================================
+
+Explicit sizes 
+^^^^^^^^^^^^^^
+The sizes of data types such as `long` and `double` vary by platform. This must
+be kept in mind because most tpl format characters require a pointer argument to
+a specific-sized type, listed above. You can use explicit-sized types such as
+`int32_t` (defined in `inttypes.h`) in your program if you find this helpful.
+
+[[trouble_with_double]]
+The trouble with double
++++++++++++++++++++++++
+Unfortunately there are no standard explicit-sized floating-point types-- no
+`float64_t`, for example. If you plan to serialize `double` on your platform
+using tpl's `f` format character, first be sure that your `double` is 64 bits.
+Second, if you plan to deserialize it on a different kind of CPU, be sure that
+both CPU's use the same floating-point representation such as IEEE 754.
+
+[[arrays]]
+Arrays 
+~~~~~~
+Arrays come in two kinds: *fixed-length* and *variable-length* arrays.
+Intuitively, they can be thought of like conventional C arrays and linked lists.
+In general, use fixed-length arrays if possible, and variable-length arrays
+if necessary. The variable-length arrays support more complex data types, and
+give or receive the elements to your program one by one.
+
+Fixed-length vs. Variable-length arrays
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Notation::
+    Fixed-length arrays are denoted like `i#` (a simple type followed by one or
+    more `#` signs), but variable-length arrays are denoted like `A(i)`. 
+Element handling::
+    All the elements of a fixed-length array are packed or unpacked at once. But
+    the elements of a variable-length array are packed or unpacked one by one.
+Array length::
+    The number of elements in a fixed-length array is specified before use--
+    before any data is packed. But variable-length arrays do not have a fixed
+    element count. They can have any number of elements packed into them. When
+    unpacking a variable-length array, they are unpacked one by one until they
+    are exhausted.
+Element types::
+    Elements of fixed-length arrays can be the integer, byte, double, string
+    types or structures. (This excludes format characters `BA`).  Fixed-length
+    arrays can also be multi-dimensional like `i##`. Variable-length arrays can
+    have simple or complex elements-- for example, an array of ints `A(i)`, an
+    array of int/double pairs `A(if)`, or even nested arrays like `A(A(if))`. 
+
+Before explaining all the concepts, it's illustrative to see how both kinds of
+arrays are used. Let's pack the integers 0 through 9 both ways.
+
+//|================================================================================
+//|Fixed-length array packing                 | Variable-length array packing
+//|#include "tpl.h"                           | #include "tpl.h"
+//|int main() {                               | int main() {
+//|  tpl_node *tn;                            |   tpl_node *tn;
+//|  int x[] = {0,1,2,3,4,5,6,7,8,9};         |   int x;
+//|                                           |
+//|  tn = tpl_map("i#", x, 10);               |   tn = tpl_map("A(i)", &x);
+//|  /* pack all 10 elements at once */       |   /* pack one element at a time */
+//|  tpl_pack(tn,0);                          |   for(x = 0; x < 10; x++) tpl_pack(tn,1);
+//|  tpl_dump(tn, TPL_FILE, "/tmp/fixed.tpl");|   tpl_dump(tn, TPL_FILE, "/tmp/variable.tpl");
+//|  tpl_free(tn);                            |   tpl_free(tn);
+//|}                                          | }
+//|================================================================================
+
+[[fixed_pack]]
+.Packing 0-9 as a fixed-length array
+-------------------------------------------------------------------------------
+#include "tpl.h"
+int main() {
+    tpl_node *tn;
+    int x[] = {0,1,2,3,4,5,6,7,8,9};
+
+    tn = tpl_map("i#", x, 10);
+    tpl_pack(tn,0);                         /* pack all 10 elements at once */
+    tpl_dump(tn, TPL_FILE, "/tmp/fixed.tpl");
+    tpl_free(tn);
+}
+-------------------------------------------------------------------------------
+
+Note that the length of the fixed-length array (10) was passed as an argument to
+`tpl_map()`.  The corresponding unpacking <<fixed_unpack,example>> is listed
+further below. Now let's see how we would pack 0-9 as a variable-length array:
+
+.Packing 0-9 as a variable-length array
+-------------------------------------------------------------------------------
+#include "tpl.h"
+int main() {
+    tpl_node *tn;
+    int x;
+
+    tn = tpl_map("A(i)", &x);
+    for(x = 0; x < 10; x++) tpl_pack(tn,1);  /* pack one element at a time */
+    tpl_dump(tn, TPL_FILE, "/tmp/variable.tpl");
+    tpl_free(tn);
+}
+-------------------------------------------------------------------------------
+
+Notice how we called `tpl_pack` in a loop, once for each element 0-9. Again,
+there is a corresponding unpacking <<var_unpack,example>> shown later in the
+guide. You might also notice that this time, we passed 1 as the final argument
+to tpl_pack. This is an index number designating which variable-length array
+we're packing. In this case, there is only one.
+
+[[index]]
+Index numbers 
+^^^^^^^^^^^^^
+Index numbers identify a particular variable-length array in the format string.
+Each `A(...)` in a format string has its own index number.  The index numbers
+are assigned left-to-right starting from 1. Examples:
+
+    A(i)        /* index number 1 */
+    A(i)A(i)    /* index numbers 1 and 2 */
+    A(A(i))     /* index numbers 1 and 2 (order is independent of nesting) */
+
+Special index number 0
+++++++++++++++++++++++
+The special index number 0 designates all the format characters that are not
+inside an `A(...)`.  Examples of what index 0 does (and does not) designate:
+
+    S(ius)      /* index 0 designates the whole thing */
+    iA(c)u      /* index 0 designates the i and the u */
+    c#A(i)S(ci) /* index 0 designates the c# and the S(ci) */
+
+An index number is passed to `tpl_pack` and `tpl_unpack` to specify which
+variable-length array (or non-array, in the case of index number 0) to act upon.
+
+Integers 
+~~~~~~~~
+The array examples <<fixed_pack,above>> demonstrated how integers could be
+packed.  We'll show some further examples here of unpacking integers and dealing
+with multi-dimensional arrays. The same program could be used to demonstrate
+working with byte, 16-bit shorts, 32-bit or 64-bit signed and unsigned integers
+with only a change to the data type and the format character.
+
+[[fixed_unpack]]
+.Unpacking 0-9 from a fixed-length array
+--------------------------------------------------------------------------------
+#include "tpl.h"
+int main() {
+    tpl_node *tn;
+    int x[10];
+
+    tn = tpl_map("i#", x, 10);
+    tpl_load(tn, TPL_FILE, "/tmp/fixed.tpl");
+    tpl_unpack(tn,0);  /* unpack all 10 elements at once */
+    tpl_free(tn);
+    /* now do something with x[0]...x[9].. (not shown */
+}
+--------------------------------------------------------------------------------
+
+For completeness, let's also see how to unpack a variable-length integer array.
+
+[[var_unpack]]
+.Unpacking 0-9 from a variable-length array
+-------------------------------------------------------------------------------
+#include "tpl.h"
+int main() {
+    tpl_node *tn;
+    int x;
+
+    tn = tpl_map("A(i)", &x);
+    tpl_load(tn, TPL_FILE, "/tmp/variable.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("%d\n",x); /* unpack one by one */
+    tpl_free(tn);
+}
+-------------------------------------------------------------------------------
+
+[[multidim_int]]
+Multi-dimensional arrays
+^^^^^^^^^^^^^^^^^^^^^^^^
+A multi-dimensional matrix of integers can be packed and unpacked the same way
+as any fixed-length array. 
+
+  int xy[XDIM][YDIM];
+  ...
+  tn = tpl_map("i##", xy, XDIM, YDIM);
+  tpl_pack(tn, 0);
+
+This single call to `tpl_pack` packs the entire matrix.
+
+Strings 
+~~~~~~~
+Tpl can serialize C strings. A different format is used for `char*` vs. `char[ ]`
+as described below. Let's look at `char*` first:
+
+.Packing a string
+-------------------------------------------------------------------------------
+    #include "tpl.h"
+
+    int main() {
+        tpl_node *tn;
+        char *s = "hello, world!";
+        tn = tpl_map("s", &s);
+        tpl_pack(tn,0);  /* copies "hello, world!" into the tpl */
+        tpl_dump(tn,TPL_FILE,"string.tpl");
+        tpl_free(tn);
+    }
+-------------------------------------------------------------------------------
+
+The `char*` must point to a null-terminated string or be a `NULL` pointer.
+
+When deserializing (unpacking) a C string, space for it will be allocated
+automatically, but you are responsible for freeing it (unless it is `NULL`):
+
+.Unpacking a string
+-------------------------------------------------------------------------------
+    #include "tpl.h"
+
+    int main() {
+        tpl_node *tn;
+        char *s;
+        tn = tpl_map("s", &s);
+        tpl_load(tn,TPL_FILE,"string.tpl");
+        tpl_unpack(tn,0);   /* allocates space, points s to "hello, world!" */
+        printf("unpacked %s\n", s);
+        free(s);            /* our responsibility to free s */
+        tpl_free(tn);
+    }
+-------------------------------------------------------------------------------
+
+char* vs char[ ]
+^^^^^^^^^^^^^^^^
+The `s` format character is only for use with `char*` types. In the example
+above, `s` is a `char*`. If it had been a `char s[14]`, we would use the format
+characters `c#` to pack or unpack it, as a fixed-length character array. (This
+unpacks the characters "in-place", instead of into a dynamically allocated
+buffer). Also, a fixed-length buffer described by `c#` need not be
+null-terminated.
+
+Arrays of strings
+^^^^^^^^^^^^^^^^^
+You can use fixed- or variable-length arrays of strings in tpl. An example of
+packing a fixed-length two-dimensional array of strings is shown here.
+
+  char *labels[2][3] = { {"one", "two", "three"},
+                         {"eins", "zwei", "drei" } };
+  tpl_node *tn;
+  tn = tpl_map("s##", labels, 2, 3);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+Later, when unpacking these strings, the programmer must remember to free them
+one by one, after they are no longer needed. 
+
+  char *olabels[2][3];
+  int i,j;
+
+  tn = tpl_map("s##", olabels, 2, 3);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  for(i=0;i<2;i++) {
+    for(j=0;j<3;j++) {
+      printf("%s\n", olabels[i][j]);
+      free(olabels[i][j]);
+    }
+  }
+
+Binary buffers
+~~~~~~~~~~~~~~
+Packing an arbitrary-length binary buffer (tpl format character `B`) makes use
+of the `tpl_bin` structure.  You must declare this structure and populate it
+with the address and length of the binary buffer to be packed. 
+
+.Packing a binary buffer
+-------------------------------------------------------------------------------
+    #include "tpl.h"
+    #include <sys/time.h>
+
+    int main() {
+        tpl_node *tn;
+        tpl_bin tb;
+
+        /* we'll use a timeval as our guinea pig */
+        struct timeval tv;       
+        gettimeofday(&tv,NULL);  
+
+        tn = tpl_map( "B", &tb );
+        tb.sz = sizeof(struct timeval);  /* size of buffer to pack */
+        tb.addr = &tv;                   /* address of buffer to pack */
+        tpl_pack( tn, 0 );
+        tpl_dump(tn, TPL_FILE, "bin.tpl");
+        tpl_free(tn);
+    }
+-------------------------------------------------------------------------------
+
+When you unpack a binary buffer, tpl will automatically allocate it, and will
+populate your `tpl_bin` structure with its address and length. You are
+responsible for eventually freeing the buffer.
+
+.Unpacking a binary buffer
+-------------------------------------------------------------------------------
+    #include "tpl.h"
+
+    int main() {
+        tpl_node *tn;
+        tpl_bin tb;
+
+        tn = tpl_map( "B", &tb );
+        tpl_load( tn, TPL_FILE, "bin.tpl" );
+        tpl_unpack( tn, 0 );
+        tpl_free(tn);
+
+        printf("binary buffer of length %d at address %p\n", tb.sz, tb.addr);
+        free(tb.addr);  /* our responsibility to free it */
+    }
+-------------------------------------------------------------------------------
+
+Structures
+~~~~~~~~~~
+You can use tpl to pack and unpack structures, and arrays of structures.
+
+    struct ci {
+        char c;
+        int i;
+    };
+    struct ci s = {'a', 1};
+
+    tn = tpl_map("S(ci)", &s);  /* pass structure address */
+    tpl_pack(tn, 0);
+    tpl_dump(tn, TPL_FILE, "struct.tpl");
+    tpl_free(tn);
+
+As shown, omit the individual arguments for the format characters inside the
+parenthesis. The exception is for fixed-length arrays; when `S(...)` contains a
+`#` character, its length argument is required: `tpl_map("S(f#i)", &s, 10);`
+
+When using the `S(...)` format, the only characters allowed inside the
+parentheses are `iujvcsfIU#$()`.
+
+Structure arrays
+^^^^^^^^^^^^^^^^
+Arrays of structures are the same as simple arrays. Fixed- or variable- length
+arrays are supported.
+
+  struct ci sa[100], one;
+
+  tn = tpl_map("S(ci)#", sa, 100);  /* fixed-length array of 100 structures */
+  tn = tpl_map("A(S(ci))", &one);   /* variable-length array (one at a time)*/
+
+The differences between fixed- and variable-length arrays are explained in the 
+<<arrays,Arrays>> section.
+
+Nested structures
+^^^^^^^^^^^^^^^^^
+When dealing with nested structures, the outermost structure uses the `S` format
+character, and the inner nested structures use the `$` format. Only the 
+'outermost' structure's address is given to `tpl_map`.
+
+  struct inner_t {
+    char a;
+  }
+
+  struct outer_t {
+    char b;
+    struct inner_t i;
+  }
+
+  tpl_node *tn;
+  struct outer_t outer = {'b', {'a'}};
+
+  tn = tpl_map("S(c$(c))", &outer);
+
+Structures can nest to any level. Currently tpl does not support fixed-length
+array suffixes on inner structures.  However the outermost structure can have a
+length suffix even if it contains some nested structures. 
+
+Linked lists
+~~~~~~~~~~~~
+While tpl has no specific data type for a linked list, the technique for
+packing them is illustrated here.  First describe your list element as a
+format string and then surround it with `A(...)` to describe it as
+variable-length array.  Then, using a temporary variable, iterate over each
+list element, copying it to the temporary variable and packing it.
+
+  struct element {
+    char c;
+    int i;
+    struct element *next;
+  }
+
+  struct element *list, *i, tmp;
+  tpl_node *tn;
+
+  /* add some elements to list.. (not shown)*/
+
+  tn = tpl_map("A(ci)", &tmp);
+  for(i = list; i != NULL; i=i->next) {
+    tmp = *i; 
+    tpl_pack(tn, 1);
+  }
+  tpl_dump(tn,TPL_FILE,"list.tpl");
+  tpl_free(tn);
+
+Unpacking is similar. The `for` loop is just replaced with:
+
+  while( tpl_unpack(tn,1) > 0) {
+    struct element *newelt = malloc(sizeof(struct element));
+    *newelt = tmp;
+    add_to_list(list, newelt);
+  }
+
+As you can see, tpl does not reinstate the whole list at once-- just one
+element at a time. You need to link the elements manually. A future release of
+tpl may support 'pointer swizzling' to make this easier.
+
+API
+---
+
+[[tpl_map]]
+tpl_map
+~~~~~~~
+The only way to create a tpl is to call `tpl_map()`. The first argument is the
+<<format,format string>>. This is followed by a list of arguments as required by
+the particular characters in the format string. E.g,
+
+    tpl_node *tn;
+    int i;
+    tn = tpl_map( "A(i)", &i );
+
+The function creates a mapping between the items in the format string and the C
+program variables whose addresses are given. Later, the C variables will be read
+or written as the tpl is packed or unpacked.
+
+This function returns a `tpl_node*` on success, or `NULL` on failure. 
+
+[[tpl_pack]]
+tpl_pack
+~~~~~~~~
+The function `tpl_pack()` packs data into a tpl. The arguments to
+`tpl_pack()` are a `tpl_node*` and an <<index,index number>>.
+
+    tn = tpl_map("A(i)A(c)", &i, &c);
+    for(i=0; i<10; i++) tpl_pack(tn, 1);    /* pack 0-9 into index 1 */
+    for(c='a; c<='z'; c++) tpl_pack(tn, 2); /* pack a-z into index 2 */
+
+.Data is copied when packed
+********************************************************************************
+Every call to `tpl_pack()` immediately 'copies' the data being packed. Thus
+the program is free to immediately overwrite or re-use the packed variables.
+********************************************************************************
+
+Index number 0
+^^^^^^^^^^^^^^
+It is necessary to pack index number 0 only if the format string contains
+characters that are not inside an `A(...)`, such as the `i` in the format string
+`iA(c)`.
+
+Variable-length arrays
+^^^^^^^^^^^^^^^^^^^^^^
+
+Adding elements to an array
++++++++++++++++++++++++++++
+To add elements to a variable-length array, call `tpl_pack()` repeatedly.  Each
+call adds another element to the array. 
+
+Zero-length arrays are ok
++++++++++++++++++++++++++
+It's perfectly acceptable to pack nothing into a variable-length array,
+resulting in a zero-length array.  
+
+[[nested_pack]]
+Packing nested arrays
++++++++++++++++++++++
+In a format string containing a nested, variable-length array, such as
+`A(A(s))`, the inner, child array should be packed prior to the parent array.
+
+When you pack a parent array, a "snapshot" of the current child array is placed
+into the parent's new element.  Packing a parent array also empties the child
+array. This way, you can pack new data into the child, then pack the parent
+again. This creates distinct parent elements which each contain distinct child
+arrays.
+
+[TIP]
+When dealing with nested arrays like `A(A(i))`, 'pack' them from the "inside
+out" (child first), but 'unpack' them from the "outside in" (parent first).
+
+The example below creates a tpl having the format string `A(A(c))`.  
+
+.Packing nested arrays
+--------------------------------------------------------------------------------
+#include "tpl.h"
+
+int main() {
+    char c;
+    tpl_node *tn;
+
+    tn = tpl_map("A(A(c))", &c);
+
+    for(c='a'; c<'c'; c++) tpl_pack(tn,2);  /* pack child (twice) */
+    tpl_pack(tn, 1);                        /* pack parent */
+
+    for(c='1'; c<'4'; c++) tpl_pack(tn,2);  /* pack child (three times) */
+    tpl_pack(tn, 1);                        /* pack parent */
+
+    tpl_dump(tn, TPL_FILE, "test40.tpl");
+    tpl_free(tn);
+}
+--------------------------------------------------------------------------------
+
+This creates a nested array in which the parent has two elements: the first
+element is the two-element nested array 'a', 'b'; and the second element is
+the three-element nested array '1', '2', '3'. 
+The <<nested_unpack,nested unpacking example>> shows how this tpl is unpacked.
+
+[[tpl_dump]]
+tpl_dump
+~~~~~~~~
+After packing a tpl, `tpl_dump()` is used to write the tpl image to a file,
+memory buffer or file descriptor. The corresponding modes are shown below. A
+final mode is for querying the output size without actually performing the dump.
+
+[width="80%",options="header",cols="30^d,70m",grid="none"]
+|================================================================================
+|Write to...      |Usage                                                  
+|file             |tpl_dump(tn, TPL_FILE, "file.tpl" );                   
+|file descriptor  |tpl_dump(tn, TPL_FD, 2);                               
+|memory           |tpl_dump(tn, TPL_MEM, &addr, &len );                   
+|caller's memory  |tpl_dump(tn, TPL_MEM\|TPL_PREALLOCD, buf, sizeof(buf));
+|just get size    |tpl_dump(tn, TPL_GETSIZE, &sz);                        
+|================================================================================
+
+The first argument is the `tpl_node*` and the second is one of these constants:
+
+`TPL_FILE`::
+    Writes the tpl to a file whose name is given in the following argument.
+    The file is created with permissions 664 (`rw-rw-r--`) unless further
+    restricted by the process `umask`.
+`TPL_FD`::
+    Writes the tpl to the file descriptor given in the following argument.
+    The descriptor can be either blocking or non-blocking, but will busy-loop
+    if non-blocking and the contents cannot be written immediately.
+`TPL_MEM`::
+    Writes the tpl to a memory buffer. The following two arguments must be a
+    `void\*\*` and a `size_t*`. The function will allocate a buffer and store
+    its address and length into these locations.  The caller is responsible to
+    `free()` the buffer when done using it. 
+`TPL_MEM|TPL_PREALLOCD`::
+    Writes the tpl to a memory buffer that the caller has already allocated or
+    declared. The following two arguments must be a `void*` and a `size_t`
+    specifying the buffer address and size respectively. (If the buffer is of
+    insufficient size to receive the tpl dump, the function will return -1).
+    This mode can be useful in conjunction with `tpl_load` in `TPL_EXCESS_OK`
+    mode, as shown <<excess_ok,here.>>
+`TPL_GETSIZE`::
+    This special mode does not actually dump the tpl. Instead it places the size
+    that the dump 'would' require into the `uint32_t` pointed to by the
+    following argument.
+
+The return value is 0 on success, or -1 on error. 
+    
+The `tpl_dump()` function does not free the tpl.  Use `tpl_free()` to release
+the tpl's resources when done.
+
+[TIP]
+.Back-to-back tpl images require no delimiter
+If you want to store a series of tpl images, or transmit sequential tpl images
+over a socket (perhaps as messages to another program), you can simply dump them
+sequentially without needing to add any delimiter for the individual tpl images.
+Tpl images are internally delimited, so `tpl_load` will read just one at a time
+even if multiple images are contiguous.
+
+[[tpl_load]]
+tpl_load
+~~~~~~~~
+This API function reads a previously-dumped tpl image from a file, memory
+buffer or file descriptor, and prepares it for subsequent unpacking.  The format
+string specified in the preceding call to `tpl_map()` will be cross-checked
+for equality with the format string stored in the tpl image.
+
+    tn = tpl_map( "A(i)", &i );
+    tpl_load( tn, TPL_FILE, "demo.tpl" );  
+
+The first argument to `tpl_load()` is the `tpl_node*`.  The second argument is
+one of the constants:
+
+`TPL_FILE`::
+    Loads the tpl from the file named in the following argument. It is also
+    possible to bitwise-OR this flag with `TPL_EXCESS_OK` as explained below.
+`TPL_MEM`::
+    Loads the tpl from a memory buffer. The following two arguments must be a
+    `void*` and a `size_t`, specifying the buffer address and size,
+    respectively.  The caller must not free the memory buffer until after
+    freeing the tpl with `tpl_free()`. (If the caller wishes to hand over
+    responsibility for freeing the memory buffer, so that it's automatically
+    freed along with the tpl when `tpl_free()` is called, the constant
+    `TPL_UFREE` may be bitwise-OR'd with `TPL_MEM` to achieve this).
+    Furthermore, `TPL_MEM` may be bitwise-OR'd with `TPL_EXCESS_OK`, explained
+    below.
+`TPL_FD`::
+    Loads the tpl from the file descriptor given in the following argument.
+    The descriptor is read until one complete tpl image is loaded; no bytes
+    past the end of the tpl image will be read.  The descriptor can be either
+    blocking or non-blocking, but will busy-loop if non-blocking and the
+    contents cannot be read immediately. 
+
+During loading, the tpl image will be extensively checked for internal validity.
+
+This function returns 0 on success or -1 on error. 
+
+[[excess_ok]]
+`TPL_EXCESS_OK`
+^^^^^^^^^^^^^^^
+When reading a tpl image from a file or memory (but not from a file descriptor)
+the size of the file or memory buffer must exactly equal that of the tpl image
+stored therein. In other words, no excess trailing data beyond the tpl image is
+permitted. The bit flag `TPL_EXCESS_OK` can be OR'd with `TPL_MEM` or `TPL_FILE`
+to relax this requirement. 
+
+A situation where this flag can be useful is in conjunction with `tpl_dump` in
+the `TPL_MEM|TPL_PREALLOCD` mode. In this example, the program does not concern
+itself with the actual tpl size as long as `LEN` is sufficiently large.
+
+  char buf[LEN];  /* will store and read tpl images here */
+  ...
+  tpl_dump(tn, TPL_MEM|TPL_PREALLOCD, buf, LEN);
+  ...
+  tpl_load(tn, TPL_MEM|TPL_EXCESS_OK, buf, LEN);
+
+
+
+
+[[tpl_unpack]]
+tpl_unpack
+~~~~~~~~~~
+The `tpl_unpack()` function unpacks data from the tpl. When data is unpacked,
+it is copied to the C program variables originally specified in `tpl_map()`.
+The first argument to `tpl_unpack` is the `tpl_node*` for the tpl and the
+second argument is an <<index,index number>>.
+
+    tn = tpl_map( "A(i)A(c)", &i, &c );
+    tpl_load( tn, TPL_FILE, "nested.tpl" );
+    while (tpl_unpack( tn, 1) > 0) printf("i is %d\n", i); /* unpack index 1 */
+    while (tpl_unpack( tn, 2) > 0) printf("c is %c\n", c); /* unpack index 2 */
+
+Index number 0
+^^^^^^^^^^^^^^
+It is necessary to unpack index number 0 only if the format string contains
+characters that are not inside an `A(...)`, such as the `i` in the format string
+`iA(c)`.
+
+Variable-length arrays
+^^^^^^^^^^^^^^^^^^^^^^
+
+Unpacking elements from an array
+++++++++++++++++++++++++++++++++
+For variable-length arrays, each call to `tpl_unpack()` unpacks another element.
+The return value can be used to tell when you're done: if it's positive, an
+element was unpacked; if it's 0, nothing was unpacked because there are no more
+elements. A negative retun value indicates an error (e.g. invalid index number).
+In this document, we usually unpack variable-length arrays using a `while` loop:
+
+    while( tpl_unpack( tn, 1 ) > 0 ) {
+        /* got another element */
+    }
+
+Array length
+++++++++++++
+When unpacking a variable-length array, it may be convenient to know ahead of
+time how many elements will need to be unpacked.  You can use `tpl_Alen()` to
+get this number.
+
+[[nested_unpack]]
+Unpacking nested arrays
++++++++++++++++++++++++
+In a format string containing a nested variable-length array such as `A(A(s))`,
+unpack the outer, parent array before unpacking the child array. 
+
+When you unpack a parent array, it prepares the child array for unpacking.
+After unpacking the elements of the child array, the program can repeat the
+process by unpacking another parent element, then the child elements, and so on.
+The example below unpacks a tpl having the format string `A(A(c))`.  
+
+.Unpacking nested arrays
+--------------------------------------------------------------------------------
+#include "tpl.h"
+#include <stdio.h>
+
+int main() {
+    char c;
+    tpl_node *tn;
+
+    tn = tpl_map("A(A(c))", &c);
+
+    tpl_load(tn, TPL_FILE, "test40.tpl");
+    while (tpl_unpack(tn,1) > 0) {
+        while (tpl_unpack(tn,2) > 0) printf("%c ",c);
+        printf("\n");
+    }
+    tpl_free(tn);
+}
+--------------------------------------------------------------------------------
+
+The file `test40.tpl` is from the <<nested_pack,nested packing example>>. When
+run, this program prints:
+
+    a b 
+    1 2 3 
+
+[[tpl_free]]
+tpl_free
+~~~~~~~~
+The final step for any tpl is to release it using `tpl_free()`. Its only
+argument is the the `tpl_node*` to free.
+    
+    tpl_free( tn );
+
+This function does not return a value (it is `void`).
+
+[[tpl_alen]]
+tpl_Alen
+~~~~~~~~
+This function takes a `tpl_node*` and an index number and returns an `int`
+specifying the number of elements in the variable-length array.
+
+    num_elements = tpl_Alen(tn, index);
+
+This is mainly useful for programs that unpack data and need to know ahead of
+time the number of elements that will need to be unpacked. (It returns the
+current number of elements; it will decrease as elements are unpacked).
+
+[[tpl_peek]]
+tpl_peek
+~~~~~~~~
+This function peeks into a file or a memory buffer containing a tpl image and
+and returns a copy of its format string.  It can also peek at the lengths of
+any fixed-length arrays in the format string, or it can also peek into the data
+stored in the tpl.  
+
+Format peek
+^^^^^^^^^^^
+The format string can be obtained
+like this:
+
+    fmt = tpl_peek(TPL_FILE, "file.tpl");   
+    fmt = tpl_peek(TPL_MEM, addr, sz); 
+
+On success, a copy of the format string is returned. The caller must eventually
+free it. On error, such as a non-existent file, or an invalid tpl image, it
+returns `NULL`.
+
+Array length peek
+^^^^^^^^^^^^^^^^^
+The lengths of all fixed-length arrays in the format string can be queried using
+the `TPL_FXLENS` mode. It provides the number of such fixed-length arrays and
+their lengths. If the former is non-zero, the caller must free the latter array
+when finished. The format string itself must also be freed.
+
+    uint32_t num_fxlens, *fxlens, j;
+    fmt = tpl_peek(TPL_FILE|TPL_FXLENS, filename, &num_fxlens, &fxlens);
+    if (fmt) {
+      printf("format %s, num_fxlens %u\n", fmt, num_fxlens);
+      for(j=0; j<num_fxlens; j++) printf("fxlens[%u] %u\n", j, fxlens[j]);
+      if (num_fxlens > 0) free(fxlens);
+      free(fmt);
+    }
+
+The `TPL_FXLENS` mode is mutually exclusive with `TPL_DATAPEEK`.
+
+
+Data peek
+^^^^^^^^^
+To peek into the data, additional arguments are used. This is a quick
+alternative to mapping, loading and unpacking the tpl, but peeking is limited
+to the data in index 0. In other words, no peeking into `A(...)` types.
+Suppose the tpl image in `file.tpl` has the format string `siA(i)`. Then the
+index 0 format characters are `si`. This is how to peek at their content:
+
+  char *s;
+  int i;
+  fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "file.tpl", "si", &s, &i);
+
+Now `s`, `i`, and `fmt` have been populated with data.  The caller must
+eventually free `fmt` and `s` because they are allocated strings.
+Of course, it works with `TPL_MEM` as well as `TPL_FILE`.  Notice that
+`TPL_DATAPEEK` was OR'd with the mode. You can also specify 'any leading
+portion' of the index 0 format if you don't want to peek at the whole thing: 
+
+  fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "file.tpl", "s", &s);
+
+The `TPL_DATAPEEK` mode is mutually exclusive with `TPL_FXLENS`.
+
+Structure peek
+++++++++++++++
+Lastly you can peek into `S(...)` structures in index 0, but omit the
+surrounding `S(...)` in the format, and specify an argument to receive
+each structure member individually. You can specify any leading portion
+of the structure format. For example if `struct.tpl` has the format string
+`S(si)`, you can peek at its data in these ways:
+
+  fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "struct.tpl", "s", &s);
+  fmt = tpl_peek(TPL_FILE | TPL_DATAPEEK, "struct.tpl", "si", &s, &i);
+
+[[tpl_jot]]
+tpl_jot
+~~~~~~~
+This is a quick shortcut for generating a tpl. It can be used instead of the
+usual "map, pack, dump, and free" lifecycle. With `tpl_jot` all those steps are
+handled for you.  It only works for simple formats-- namely, those without
+`A(...)` in their format string. Here is how it is used:
+
+  char *hello = "hello", *world = "world";
+  tpl_jot( TPL_FILE, "file.tpl", "ss", &hello, &world);
+
+It supports the three standard modes, `TPL_FILE`, `TPL_FD` and `TPL_MEM`.
+It returns -1 on failure (such as a bad format string or error writing the
+file) or 0 on success.
+
+[[hooks]]
+tpl_hook
+~~~~~~~~
+Most users will just leave these hooks at their default values. You can change
+these hook values if you want to modify tpl's internal memory management and
+error reporting behavior.
+
+A global structure called `tpl_hook` encapsulates the hooks.  A program can
+reconfigure any hook by specifying an alternative function whose prototype
+matches the default. For example:
+
+    #include "tpl.h"
+    extern tpl_hook_t tpl_hook;
+
+    int main() {
+        tpl_hook.oops = printf;
+        ...
+    }
+
+.Configurable hooks
+[width="90%",options="header",cols="m,d,m",grid="none"]
+|================================================================================
+|Hook                |Description                  | Default
+|tpl_hook.oops       |log error messages           | tpl_oops 
+|tpl_hook.malloc     |allocate memory              | malloc
+|tpl_hook.realloc    |reallocate memory            | realloc
+|tpl_hook.free       |free memory                  | free
+|tpl_hook.fatal      |log fatal message and exit   | tpl_fatal
+|tpl_hook.gather_max |tpl_gather max image size    | 0 (unlimited)
+|================================================================================
+
+The oops hook
+^^^^^^^^^^^^^
+The `oops` has the same prototype as `printf`. The built-in default oops
+handling function writes the error message to `stderr`.
+
+The fatal hook
+^^^^^^^^^^^^^^
+The fatal hook is invoked when a tpl function cannot continue because of an out-
+of-memory condition or some other usage violation or inconsistency. It has this
+prototype:
+
+  void fatal_fcn(char *fmt, ...);
+
+The `fatal` hook must not return. It must either exit, 'or' if the program needs
+to handle the failure and keep executing, `setjmp` and `longjmp` can be used.
+The default behavior is to `exit(-1)`.
+
+.Using longjmp in a fatal error handler
+--------------------------------------------------------------------------------
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "tpl.h"
+
+jmp_buf env;
+extern tpl_hook_t tpl_hook;
+
+void catch_fatal(char *fmt, ...) {
+  va_list ap;
+
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+  longjmp(env,-1);                /* return to setjmp point */
+}
+
+int main() {
+  int err;
+  tpl_node *tn;
+  tpl_hook.fatal = catch_fatal;    /* install fatal handler */
+
+  err = setjmp(env); /* on error, control will return here  */
+  if (err) {
+    printf("caught error!\n");
+    return -1;
+  }
+
+  tn = tpl_map("@");              /* generate a fatal error */
+  printf("program ending, without error\n");
+  return 0;
+}
+--------------------------------------------------------------------------------
+
+This example is included in `tests/test123.c`. When run, this program prints:
+
+  unsupported option @
+  failed to parse @
+  caught error!
+
+
+tpl_gather
+~~~~~~~~~~
+
+.Most programs don't need this
+********************************************************************************
+Normally, `tpl_load()` is used to read a tpl image having an expected format
+string.  A more generic operation is to acquire a tpl image whose format string is
+unknown. E.g., a generic message-receiving function might gather tpl images of
+varying format and route them to their final destination. This is the purpose of
+`tpl_gather`. It produces a memory buffer containing one tpl image. If there
+are multiple contiguous images in the input, it gathers exactly one image at a 
+time.
+********************************************************************************
+
+The prototype for this function is:
+
+    int tpl_gather( int mode, ...);
+
+The `mode` argument is one of three constants listed below, which must be
+followed by the mode-specific required arguments: 
+
+    TPL_GATHER_BLOCKING,    int fd, void **img, size_t *sz
+    TPL_GATHER_NONBLOCKING, int fd, tpl_gather_t **gs, tpl_gather_cb *cb, void *data
+    TPL_GATHER_MEM,         void *addr, size_t sz, tpl_gather_t **gs, tpl_gather_cb *cb, void *data
+
+[NOTE]
+.`tpl_hook.gather_max` 
+All modes honor `tpl_hook.gather_max`, specifying the maximum byte size for a
+tpl image to be gathered (the default is unlimited, signified by 0). If a source
+attempts to send a tpl image larger than this maximum, whatever partial image
+has been read will be discarded, and no further reading will take place; in this
+case `tpl_gather` will return a negative (error) value to inform the caller that
+it should stop gathering from this source, and close the originating file
+descriptor if there is one. (The whole idea is to prevent untrusted sources from
+sending extremely large tpl images which would consume too much memory.)
+
+
+`TPL_GATHER_BLOCKING`
+^^^^^^^^^^^^^^^^^^^
+In this mode, `tpl_gather` blocks while reading file descriptor `fd` until one
+complete tpl image is read. No bytes past the end of the tpl image will be read.
+The address of the buffer containing the image is returned in `img` and its size
+is placed in `sz`. The caller is responsible for eventually freeing the buffer.
+The function returns 1 on success, 0 on end-of-file, or a negative number on
+error.
+
+`TPL_GATHER_NONBLOCKING`
+^^^^^^^^^^^^^^^^^^^^^^
+This mode is for non-blocking, event-driven programs that implement their
+own file descriptor readability testing using `select()` or the like. In this
+mode, tpl images are gathered in chunks as data becomes readable. Whenever a
+full tpl image has been gathered, it invokes a caller-specified callback to do
+something with the image.  The arguments are the file descriptor `fd` which the
+caller has determined to be readable and which must be in non-blocking mode, a
+pointer to a file-descriptor-specific handle which the caller has declared
+(explained below); a callback to invoke when a tpl image has been read; and an
+opaque pointer that will passed to the callback.
+
+For each file descriptor on which `tpl_gather` will be used, the caller must
+declare a `tpl_gather_t*` and initialize it to `NULL`. Thereafter it will be
+used internally by `tpl_gather` whenever data is readable on the descriptor.
+
+The callback will only be invoked whenever `tpl_gather()` has accumulated one
+complete tpl image. It must have this prototype:
+
+    int (tpl_gather_cb)(void *img, size_t sz, void *data);
+
+The callback can do anything with the tpl image but it must not free it. It can
+be copied if it needs to survive past the callback's return. The callback should
+return 0 under normal circumstances, or a negative number to abort; that is,
+returning a negative number causes `tpl_gather` itself to discard any remaining
+full or partial tpl images that have been read, and to return a negative number
+(-4 in particular) to signal its caller to close the file descriptor.
+
+The return value of `tpl_gather()` is negative if an error occured or 0 if a
+normal EOF was encountered-- both cases require that the caller close the file
+descriptor (and stop monitoring it for readability, obviously). If the return
+value is positive, the function succeeded in gathering whatever data was
+currently readable, which may have been a partial tpl image, or one or more
+complete images.
+
+Typical Usage
++++++++++++++
+The program will have established a file descriptor in non-blocking mode and
+be monitoring it for readability, using `select()`. Whenever it's readable, the
+program calls `tpl_gather()`. In skeletal terms:
+
+    tpl_gather_t *gt=NULL;
+    int rc;
+
+    void fd_is_readable(int fd) {
+      rc = tpl_gather( TPL_GATHER_NONBLOCKING, fd, &gt, callback, NULL );
+      if (rc <= 0) {
+          close(fd);               /* got eof or fatal */
+          stop_watching_fd(fd);
+      }
+    }
+
+    int callback( void *img, size_t sz, void *data ) {
+      printf("got a tpl image\n"); /* do something with img. do not free it. */
+      return 0;                    /* normal (no error) */
+    }
+
+`TPL_GATHER_MEM`
+^^^^^^^^^^^^^^
+This mode is identical to `TPL_GATHER_NONBLOCKING` except that it gathers from a
+memory buffer instead of from a file descriptor. In other words, if some other
+layer of code-- say, a decryption function (that is decrypting fixed-size
+blocks) produces tpl fragments one-by-one, this mode can be used to reconstitute
+the tpl images and invoke the callback for each one. Its parameters are the same
+as for the `TPL_GATHER_NONBLOCKING` mode except that instead of a file
+descriptor, it takes a buffer address and size. The return values are also the
+same as for `TPL_GATHER_NONBLOCKING` noting of course there is no file
+descriptor to close on a non-positive return value.
+
+
+// vim: set tw=80 wm=2 syntax=asciidoc: 
+
diff --git a/libs/libtpl-1.5/lang/perl/Tpl.pm b/libs/libtpl-1.5/lang/perl/Tpl.pm
new file mode 100755 (executable)
index 0000000..b6c4104
--- /dev/null
@@ -0,0 +1,475 @@
+package Tpl;
+
+# Copyright (c) 2005-2007, Troy Hanson      http://tpl.sourceforge.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:
+# 
+#     * 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.
+#     * Neither the name of the copyright holder nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+# 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.
+
+use strict;
+use warnings;
+use Config;  # to get the size of "double" on this platform
+
+use bytes;   # always use byte (not unicode char) offsets w/tpl images
+
+our $VERSION = 1.1;
+
+# tpl object is a reference to a hash with these keys:
+#
+# A(0):  
+# ... :  
+# A(n):  
+#
+# where each A(i) refers to an A node, except A(0) is the root node.
+#
+# For each hash key (A node or root node), the value of that key is
+# a list reference. The members are of the list are the node's children.
+# They're represented as "Ai" (for A nodes) where i is a positive integer;
+# for non-A nodes the representation is [type,addr] e.g. [ "i", \$some_integer]
+# 
+# For example, 
+# Tpl->map("iA(ib)", \$x, \$y, \$z);
+# returns a tpl object which is a reference to a hash with these keys/values:
+#
+# $self->{A0} = [ [ "i", \$x ], "A1" ];
+# $self->{A1} = [ [ "i", \$y ], [ "b", \$z ] ];
+#
+# Now if A1 (that is, the "A(ib)" node) is packed, the tpl object acquires
+# another hash key/value:
+# $self->{P1} = [ $binary_int, $binary_byte ];  
+# and repeated calls to pack A1 append further $binary elements.
+#
+sub tpl_map {
+    my $invocant = shift;
+    my $class = ref($invocant) || $invocant;
+    my $fmt = shift;
+    my @astack = (0); # stack of current A node's lineage in tpl tree
+    my $a_count=0;    # running count of A's, thus an index of them
+    my $self = {};    # populate below
+    my ($lparen_level,$expect_lparen,$in_structure)=(0,0,0);
+    for (my $i=0; $i < length $fmt; $i++) {
+        my $c = substr($fmt,$i,1);
+        if ($c eq 'A') {
+            $a_count++;
+            push @{ $self->{"A" . $astack[-1]} }, "A$a_count";
+            push @astack, $a_count;
+            $expect_lparen=1;
+        } elsif ($c eq '(') {
+            die "invalid format $fmt" unless $expect_lparen;
+            $expect_lparen=0;
+            $lparen_level++;
+        } elsif ($c eq ')') {
+            $lparen_level--;
+            die "invalid format $fmt" if $lparen_level < 0;
+            die "invalid format $fmt" if substr($fmt,$i-1,1) eq '(';
+            if ($in_structure && ($in_structure-1 == $lparen_level)) {
+                $in_structure=0; 
+            } else { 
+                pop @astack;  # rparen ends A() type, not S() type 
+            }
+        } elsif ($c eq 'S') {
+            # in perl we just parse and ignore the S() construct
+            $expect_lparen=1;
+            $in_structure=1+$lparen_level; # so we can tell where S fmt ends 
+        } elsif ($c =~ /^(i|u|B|s|c|f|I|U)$/) {
+            die "invalid format $fmt" if $expect_lparen;
+            my $r = shift;
+            die "no reference for $c (position $i of $fmt)" unless ref($r);
+            if (($c eq "f") and ($Config{doublesize} != 8)) {
+               die "double not 8 bytes on this platform";
+            }
+            if (($c =~ /(U|I)/) and not defined ($Config{use64bitint})) {
+               die "Tpl.pm: this 32-bit Perl can't pack/unpack 64-bit I/U integers\n";
+            }
+            push @{ $self->{"A" . $astack[-1]} }, [ $c , $r ];
+        } elsif ($c eq "#") {
+            #  test for previous iucfIU
+            die "unallowed length modifer" unless $self->{"A" . $astack[-1]}->[-1]->[0] =~ /^(i|u|c|I|U|f)$/;
+            my $n = shift;
+            die "non-numeric # length modifer" unless $n =~ /^\d+$/;
+            push @{ $self->{"A" . $astack[-1]}->[-1] }, $n;
+            push @{ $self->{"#"}}, $n;  # master array of octothorpe lengths
+        } else {
+            die "invalid character $c in format $fmt";
+        }
+    }
+    die "invalid format $fmt" if $lparen_level != 0;
+    $self->{fmt} = $fmt;
+    bless $self;
+    return $self;
+}
+
+sub tpl_format {
+    my $self = shift;
+    return $self->{fmt};
+}
+
+sub tpl_pack {
+    my $self = shift;
+    my $i = shift;
+    die "invalid index" unless defined $self->{"A$i"};
+    die "tpl for unpacking only" if defined $self->{"loaded"};
+    $self->{"packed"}++;
+    $self->{"P$i"} = undef if $i == 0;  # node 0 doesn't accumulate
+    my @bb;
+    foreach my $node (@{ $self->{"A$i"} }) {
+        if (ref($node)) {
+            my ($type,$addr,$fxlen) = @{ $node };
+            if (defined $fxlen) { # octothorpic array 
+                push @bb, CORE::pack("l$fxlen",@$addr) if $type eq "i"; # int
+                push @bb, CORE::pack("L$fxlen",@$addr) if $type eq "u"; # uint
+                push @bb, CORE::pack("C$fxlen",@$addr) if $type eq "c"; # byte
+                push @bb, CORE::pack("d$fxlen",@$addr) if $type eq "f"; # double
+                push @bb, CORE::pack("q$fxlen",@$addr) if $type eq "I"; # int64
+                push @bb, CORE::pack("Q$fxlen",@$addr) if $type eq "U"; # uint64
+            } else {
+                # non-octothorpic singleton
+                push @bb, CORE::pack("l",$$addr) if $type eq "i"; # int
+                push @bb, CORE::pack("L",$$addr) if $type eq "u"; # uint
+                push @bb, CORE::pack("C",$$addr) if $type eq "c"; # byte
+                push @bb, CORE::pack("d",$$addr) if $type eq "f"; # double (8 byte)
+                push @bb, CORE::pack("q",$$addr) if $type eq "I"; # int64
+                push @bb, CORE::pack("Q",$$addr) if $type eq "U"; # uint64
+                if ($type =~ /^(B|s)$/) {                         # string/binary
+                    push @bb, CORE::pack("L", length($$addr));
+                    push @bb, CORE::pack("a*", $$addr);
+                }
+            }
+        } elsif ($node =~ /^A(\d+)$/) {
+            # encode array length (int) and the array data into one scalar
+            my $alen = pack("l", scalar @{ $self->{"P$1"} or [] });
+            my $abod = (join "", @{ $self->{"P$1"} or [] });
+            push @bb, $alen . $abod;
+            $self->{"P$1"} = undef;
+        } else {
+          die "internal error; invalid node symbol $node";
+        }
+    }
+    push @{ $self->{"P$i"} }, (join "", @bb);
+}
+
+sub big_endian {
+    return (CORE::unpack("C", CORE::pack("L",1)) == 1) ? 0 : 1;
+}
+
+sub tpl_dump {
+    my $self = shift;
+    my $filename = shift;
+
+    $self->tpl_pack(0) if not defined $self->{"P0"};  
+    my $format = $self->tpl_format;
+    my $octothorpe_lens = CORE::pack("L*", @{ $self->{"#"} or [] });
+    my $data = (join "", @{ $self->{"P0"} });  
+    my $ov_len = length($format) + 1 + length($octothorpe_lens) + length($data) + 8;
+    my $flags = big_endian() ? 1 : 0;
+    my $preamble = CORE::pack("CLZ*", $flags, $ov_len, $format);
+    my $tpl = "tpl" . $preamble . $octothorpe_lens . $data;
+    return $tpl unless $filename;
+
+    # here for file output
+    open TPL, ">$filename" or die "can't open $filename: $!";
+    print TPL $tpl;
+    close TPL;
+}
+
+sub tpl_peek {
+    my $invocant = shift;
+    my $class = ref($invocant) || $invocant;
+    my $tplhandle = shift;
+    my $tpl;
+
+    if (ref($tplhandle)) {
+        $tpl = $$tplhandle;
+    } else {
+        open TPL, "<$tplhandle" or die "can't open $tplhandle: $!";
+        undef $/;   # slurp
+        $tpl = <TPL>;
+        close TPL;
+    }
+    die "invalid tpl file" unless ($tpl =~ /^tpl/);
+    return (unpack("Z*", substr($tpl,8)));
+}
+
+sub tpl_load {
+    my $self = shift;
+    my $tplhandle = shift;
+
+    die "tpl for packing only" if $self->{"packed"};
+    die "tpl reloading not supported" if $self->{"loaded"};
+
+    # read tpl image from file or was it passed directly via ref?
+    my $tpl;
+    if (ref($tplhandle)) {
+        $tpl = $$tplhandle;
+    } else {
+        open TPL, "<$tplhandle" or die "can't open $tplhandle: $!";
+        undef $/;   # slurp
+        $tpl = <TPL>;
+        close TPL;
+    }
+    
+    $self->{"TI"} = $tpl;
+    $self->{"TL"} = length $tpl;
+    # verify preamble
+    die "invalid image -1" unless length($tpl) >= 9;
+    die "invalid image -2" unless $tpl =~ /^tpl/;
+    my $flags = CORE::unpack("C", substr($tpl,3,1));
+    $self->{"xendian"} = 1 if (big_endian() != ($flags & 1));
+    $self->{"UF"} = ($flags & 1) ? "N" : "V";
+    my $ov_len = CORE::unpack($self->{"UF"}, substr($tpl,4,4));
+    die "invalid image -3" unless $ov_len == length($tpl);
+    my $format = CORE::unpack("Z*", substr($tpl,8));
+    die "format mismatch" unless $format eq $self->tpl_format();
+    my @octothorpe_lens = @{ $self->{"#"} or [] };
+    my $ol = 8 + length($format) + 1; # start of octothorpe lengths
+    for (my $i=0; $i < (scalar @octothorpe_lens); $i++) {
+        my $len = CORE::unpack($self->{"UF"}, substr($tpl,$ol,4));
+        my $olen = $octothorpe_lens[$i];
+        die "fixed-length array size mismatch" unless $olen == $len;
+        $ol += 4;
+    }
+    my $dv = $ol;  # start of packed data 
+    my $len = $self->serlen("A0",$dv);
+    die "invalid image -4" if $len == -1;
+    die "invalid image -5" if (length($tpl) != $len + $dv);
+    $self->{"C0"} = $dv;
+    $self->{"loaded"} = 1;
+    $self->unpackA0;   # prepare root child nodes for use
+}
+
+# byte reverse a word (any length)
+sub reversi {
+    my $word = shift;
+    my @w = split //, $word;
+    my $r = join "", (reverse @w);
+    return $r;
+}
+
+#
+# while unpacking, the object has these keys in its hash:
+# C0
+# C1
+# ...
+# C<n>
+# These are indices (into the tpl image $self->{"TI"}) from which node n
+# is being unpacked. I.e. as array elements of node n are unpacked, C<n>
+# advances through the tpl image.
+# 
+# Similarly, elements
+# N1
+# N2
+# ...
+# N<n>
+# refer to the remaining array count for node n.
+#
+sub tpl_unpack {
+    my $self = shift;
+    my $n = shift;
+    my $ax = "A$n";
+    my $cx = "C$n";
+    my $nx = "N$n";
+    my $rc;
+
+    die "tpl for packing only" if $self->{"packed"};
+    die "tpl not loaded" unless $self->{"loaded"};
+
+    # decrement count for non root array nodes
+    if ($n > 0) {
+        return 0 if $self->{$nx} <= 0;
+        $rc = $self->{$nx}--;
+    }
+
+    for my $c (@{ $self->{$ax} }) {
+        if (ref($c)) {
+            my ($type,$addr,$fxlen) = @$c;
+            if (defined $fxlen) {  # octothorpic unpack
+                @{ $addr } = (); # empty existing list before pushing elements
+                for(my $i=0; $i < $fxlen; $i++) {
+                    if ($type eq "u") {  # uint
+                        push @{ $addr }, CORE::unpack($self->{"UF"},
+                                     substr($self->{"TI"},$self->{$cx},4));
+                        $self->{$cx} += 4;
+                    } elsif ($type eq "i") { #int (see note below re:signed int)
+                        my $intbytes = substr($self->{"TI"},$self->{$cx},4);
+                        $intbytes = reversi($intbytes) if $self->{"xendian"};
+                        push @{ $addr }, CORE::unpack("l", $intbytes);
+                        $self->{$cx} += 4;
+                    } elsif ($type eq "c") { # byte
+                        push @{ $addr }, CORE::unpack("C",
+                                     substr($self->{"TI"},$self->{$cx},1));
+                        $self->{$cx} += 1;
+                    } elsif ($type eq "f") { # double
+                        my $double_bytes = substr($self->{"TI"},$self->{$cx},8);
+                        $double_bytes = reversi($double_bytes) if $self->{"xendian"};
+                        push @{ $addr }, CORE::unpack("d", $double_bytes );
+                        $self->{$cx} += 8;
+                    } elsif ($type eq "I") { #int64 
+                        my $intbytes = substr($self->{"TI"},$self->{$cx},8);
+                        $intbytes = reversi($intbytes) if $self->{"xendian"};
+                        push @{ $addr }, CORE::unpack("q", $intbytes);
+                        $self->{$cx} += 8;
+                    } elsif ($type eq "U") { #uint64 
+                        my $intbytes = substr($self->{"TI"},$self->{$cx},8);
+                        $intbytes = reversi($intbytes) if $self->{"xendian"};
+                        push @{ $addr }, CORE::unpack("Q", $intbytes);
+                        $self->{$cx} += 8;
+                    }
+                }
+            } else {
+                # non-octothorpe (singleton)
+                if ($type eq "u") {       # uint
+                    ${$addr} = CORE::unpack($self->{"UF"},
+                                 substr($self->{"TI"},$self->{$cx},4));
+                    $self->{$cx} += 4;
+                } elsif ($type eq "i") {       # int
+                    # while perl's N or V conversions unpack an unsigned
+                    # long from either big or little endian format 
+                    # respectively, when it comes to *signed* int, perl
+                    # only has 'l' (which assumes native endianness). 
+                    # So we have to manually reverse the bytes in a 
+                    # cross-endian 'int' unpacking scenario.
+                    my $intbytes = substr($self->{"TI"},$self->{$cx},4);
+                    $intbytes = reversi($intbytes) if $self->{"xendian"};
+                    ${$addr} = CORE::unpack("l", $intbytes);
+                    $self->{$cx} += 4;
+                } elsif ($type eq 'c') {  # byte
+                    ${$c->[1]} = CORE::unpack("C",
+                                 substr($self->{"TI"},$self->{$cx},1));
+                    $self->{$cx} += 1;
+                } elsif ($type eq 'f') {  # double
+                    ${$addr} = CORE::unpack("d",
+                                 substr($self->{"TI"},$self->{$cx},8));
+                    $self->{$cx} += 8;
+                } elsif ($type =~ /^(B|s)$/) {  # string/binary
+                    my $slen = CORE::unpack($self->{"UF"},
+                                 substr($self->{"TI"},$self->{$cx},4));
+                    $self->{$cx} += 4;
+                    ${$addr} = CORE::unpack("a$slen",
+                                 substr($self->{"TI"},$self->{$cx},$slen));
+                    $self->{$cx} += $slen;
+                } elsif ($type eq "I") {       # int64
+                    my $intbytes = substr($self->{"TI"},$self->{$cx},8);
+                    $intbytes = reversi($intbytes) if $self->{"xendian"};
+                    ${$addr} = CORE::unpack("q", $intbytes);
+                    $self->{$cx} += 8;
+                } elsif ($type eq "U") {       # uint64
+                    my $intbytes = substr($self->{"TI"},$self->{$cx},8);
+                    $intbytes = reversi($intbytes) if $self->{"xendian"};
+                    ${$addr} = CORE::unpack("Q", $intbytes);
+                    $self->{$cx} += 8;
+                } else { die "internal error"; }
+            }
+        } elsif ($c =~ /^A(\d+)$/) {
+            my $alen = $self->serlen($c,$self->{$cx});
+            $self->{"N$1"} = CORE::unpack($self->{"UF"},
+                     substr($self->{"TI"},$self->{$cx},4)); # get array count
+            $self->{"C$1"} = $self->{$cx} + 4;  # set array node's data start
+            $self->{$cx} += $alen;              # step over array node's data
+        } else { die "internal error"; }
+    }
+
+    return $rc;
+}
+
+# specialized function to prepare root's child A nodes for initial use
+sub unpackA0 {
+    my $self = shift;
+    my $ax = "A0";
+    my $cx = "C0";
+    my $c0 = $self->{$cx};
+
+    for my $c (@{ $self->{$ax} }) {
+        next if ref($c); # skip non-A nodes
+        if ($c =~ /^A(\d+)$/) {
+            my $alen = $self->serlen($c,$c0);
+            $self->{"N$1"} = CORE::unpack($self->{"UF"},
+                     substr($self->{"TI"},$c0,4)); # get array count
+            $self->{"C$1"} = $c0 + 4;  # set array node's data start
+            $c0 += $alen;              # step over array node's data
+        } else { die "internal error"; }
+    }
+}
+
+# ascertain serialized length of given node by walking
+sub serlen {
+    my $self = shift;
+    my $ax = shift;
+    my $dv = shift;
+
+    my $len = 0;
+
+    my $num;  
+    if ($ax eq "A0") {
+        $num = 1;
+    } else {
+        return -1 unless $self->{"TL"} >= $dv + 4;
+        $num = CORE::unpack($self->{"UF"},substr($self->{"TI"},$dv,4));
+        $dv += 4;
+        $len += 4;
+    }
+
+    while ($num-- > 0) {
+        for my $c (@{ $self->{$ax} }) {
+            if (ref($c)) {
+                my $n = 1;
+                $n = $c->[2] if (@$c > 2); # octothorpic array length
+                if ($c->[0] =~ /^(i|u)$/) {       # int/uint
+                    return -1 unless $self->{"TL"} >= $dv + 4*$n;
+                    $len += 4*$n;
+                    $dv += 4*$n;
+                } elsif ($c->[0] eq "c") {  # byte
+                    return -1 unless $self->{"TL"} >= $dv + 1*$n;
+                    $len += 1*$n;
+                    $dv += 1*$n;
+                } elsif ($c->[0] eq "f") {  # double
+                    return -1 unless $self->{"TL"} >= $dv + 8*$n;
+                    $len += 8*$n;
+                    $dv += 8*$n;
+                } elsif ($c->[0] =~ /(I|U)/) {  # int64/uint64
+                    return -1 unless $self->{"TL"} >= $dv + 8*$n;
+                    $len += 8*$n;
+                    $dv += 8*$n;
+                } elsif ($c->[0] =~ /^(B|s)$/) {  # string/binary
+                    return -1 unless $self->{"TL"} >= $dv + 4;
+                    my $slen = CORE::unpack($self->{"UF"},
+                                substr($self->{"TI"},$dv,4));
+                    $len += 4;
+                    $dv += 4;
+                    return -1 unless $self->{"TL"} >= $dv + $slen;
+                    $len += $slen;
+                    $dv += $slen;
+                } else { die "internal error" }
+            } elsif ($c =~ /^A/) {
+                my $alen = $self->serlen($c,$dv);
+                return -1 if $alen == -1;
+                $dv += $alen;
+                $len += $alen;
+            } else { die "internal error"; }
+        }
+    }
+    return $len;
+}
+
+1
diff --git a/libs/libtpl-1.5/lang/perl/tests/Makefile b/libs/libtpl-1.5/lang/perl/tests/Makefile
new file mode 100755 (executable)
index 0000000..c2dd552
--- /dev/null
@@ -0,0 +1,9 @@
+all: run_tests
+
+run_tests: 
+       perl ./do_tests
+
+.PHONY: clean
+
+clean: 
+       rm -f test*.out
diff --git a/libs/libtpl-1.5/lang/perl/tests/README b/libs/libtpl-1.5/lang/perl/tests/README
new file mode 100755 (executable)
index 0000000..8f10443
--- /dev/null
@@ -0,0 +1,29 @@
+Run 'make' to run the tests.
+
+Run 'make clean' to clean up the temporary files.
+
+Description of tests
+=============================================================================
+test1   pack A(i) to file, unpack
+test2   pack A(i) to memory, unpack
+test3   pack A(i) to memory, pipe through tplxml (to make XML)
+test4   pack A(i) to file, convert to XML, convert back to tpl (using tplxml)
+test5   pack A(b) to file, unpack
+test6   pack A(b) to memory, pipe through tplxml (to make XML)
+test7   pack A(b) to file, convert to XML, convert back to tpl (using tplxml)
+test8   pack A(s) (has embedded &, < and > in strings to test quoting in XML)
+test9   pack A(u) to file, unpack
+test10  pack A(u) to memory, convert via tplxml
+test11  pack format B using a four-byte binary buffer, unpack and print
+test12  pack A(d) to file, unpack
+test13  pack A(d) to memory, convert via tplxml
+test14  unpack big-endian i (-2) (on little-endian machine, tests reversi)
+test15  unpack little-endian i (-3) (on big-endian machine, tests reversi)
+test16  pack to mem format B using a four-byte binary buffer, unpack and print
+test17  pack and unpack S(ic)
+test18  pack and unpack i#
+test19  pack and unpack i#i#
+test20  pack A(S(ci#)) to file, convert to XML, then back to tpl (cf test81.c)
+test21  Tpl->tpl_peek in-memory image
+test22  Tpl->tpl_peek file image
+test23  test I/U (only succeeds on 64-bit perl)
diff --git a/libs/libtpl-1.5/lang/perl/tests/client.pl b/libs/libtpl-1.5/lang/perl/tests/client.pl
new file mode 100755 (executable)
index 0000000..4d471e7
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use IO::Socket::INET;
+use lib "..";
+use Tpl;
+
+our $port = 2000;
+
+# construct tpl
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+$tpl->tpl_pack(1) while ($i=shift @ARGV);
+my $request = $tpl->tpl_dump();
+
+# send to server, get response
+my $socket = IO::Socket::INET->new("localhost:$port") or die "can't connect";
+print $socket $request;
+shutdown($socket,1);       # done writing (half-close)
+undef $/;
+my $response = <$socket>;      # get reply (slurp)
+
+# decode response (or print error)
+my $total;
+my $tpl2 = Tpl->tpl_map("i", \$total);
+eval { $tpl2->tpl_load(\$response); };
+die "invalid response\n" if $@;
+$tpl2->tpl_unpack(0);
+print "total is $total\n";
diff --git a/libs/libtpl-1.5/lang/perl/tests/do_tests b/libs/libtpl-1.5/lang/perl/tests/do_tests
new file mode 100755 (executable)
index 0000000..3ca08bb
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my @tests;
+for (glob "test*[0-9]") {
+    push @tests, $_ if -e "$_.ans";
+}
+
+my $num_failed=0;
+
+for my $test (@tests) {
+    `./$test > $test.out`;
+    `diff $test.out $test.ans`;
+    print "$test failed\n" if $?;
+    $num_failed++ if $?;
+}
+
+print scalar @tests . " tests conducted, $num_failed failed.\n";
diff --git a/libs/libtpl-1.5/lang/perl/tests/server.pl b/libs/libtpl-1.5/lang/perl/tests/server.pl
new file mode 100755 (executable)
index 0000000..4faa9c6
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use IO::Socket::INET;
+use lib "..";
+use Tpl;
+
+$SIG{CHLD} = "IGNORE"; # don't create zombies
+
+our $port = 2000;
+
+sub handle_client {
+    my $client = shift;
+
+    undef $/;
+    my $request = <$client>; # get request (slurp) 
+
+    # read input array, and calculate total
+    my ($i,$total);
+    my $tpl = Tpl->tpl_map("A(i)", \$i);
+    eval { $tpl->tpl_load(\$request); };
+    die "received invalid tpl" if $@;
+    $total += $i while $tpl->tpl_unpack(1) > 0;
+
+    # formulate response and send
+    my $tpl2 = Tpl->tpl_map("i", \$total);
+    $tpl2->tpl_pack(0);
+    my $response = $tpl2->tpl_dump();
+    print $client $response;
+    close $client;
+}
+
+my $server = IO::Socket::INET->new(LocalPort => $port,
+                   Type => SOCK_STREAM,
+                   Reuse => 1,
+                   Listen => 10 )
+        or die "Can't listen on port $port: $!\n";
+
+while (1) {
+    my $client = $server->accept();
+    next unless $client;
+    # new connection
+    my $pid = fork;
+    die "can't fork: $!\n" unless defined $pid;
+    if ($pid > 0) {
+        #p arent
+        close $client;
+    } elsif ($pid == 0) {
+        # child
+        handle_client($client);
+        exit(0);
+    }
+}
+close ($server);
diff --git a/libs/libtpl-1.5/lang/perl/tests/test1 b/libs/libtpl-1.5/lang/perl/tests/test1
new file mode 100755 (executable)
index 0000000..f559e4b
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+$tpl->tpl_dump($tmp1);
+
+my $j;
+my $tpl2 = Tpl->tpl_map("A(i)",\$j);
+$tpl2->tpl_load($tmp1);
+while($tpl2->tpl_unpack(1) > 0) { print "$j\n" }
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test1.ans b/libs/libtpl-1.5/lang/perl/tests/test1.ans
new file mode 100755 (executable)
index 0000000..8b1acc1
--- /dev/null
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/libs/libtpl-1.5/lang/perl/tests/test10 b/libs/libtpl-1.5/lang/perl/tests/test10
new file mode 100755 (executable)
index 0000000..49be955
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $i;
+my $tpl = Tpl->tpl_map("A(u)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+my $img = $tpl->tpl_dump();
+
+open TPLXML, "|../tplxml" or die "can't open tplxml: $!";
+print TPLXML $img;
+close TPLXML;
diff --git a/libs/libtpl-1.5/lang/perl/tests/test10.ans b/libs/libtpl-1.5/lang/perl/tests/test10.ans
new file mode 100755 (executable)
index 0000000..4832472
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" ?>
+      <!DOCTYPE tplxml [ 
+      <!ELEMENT tplxml (A|i|u|I|U|B|s|c|f|fx)*>
+      <!ATTLIST tplxml
+         format CDATA #REQUIRED
+         fxlens CDATA #REQUIRED
+      >
+      <!ELEMENT i (#PCDATA)>
+      <!ELEMENT u (#PCDATA)>
+      <!ELEMENT I (#PCDATA)>
+      <!ELEMENT U (#PCDATA)>
+      <!ELEMENT B (#PCDATA)>
+      <!ELEMENT s (#PCDATA)>
+      <!ELEMENT c (#PCDATA)>
+      <!ELEMENT f (#PCDATA)>
+      <!ELEMENT A (el)*>
+      <!ELEMENT el (A|i|u|I|U|B|s|c|f|fx)+>
+      <!ELEMENT fx (i|u|I|U|c|f)*>
+      ]>
+<tplxml format="A(u)" fxlens="">
+  <A>
+  <el>
+    <u>0</u>
+  </el>
+  <el>
+    <u>1</u>
+  </el>
+  <el>
+    <u>2</u>
+  </el>
+  <el>
+    <u>3</u>
+  </el>
+  <el>
+    <u>4</u>
+  </el>
+  <el>
+    <u>5</u>
+  </el>
+  <el>
+    <u>6</u>
+  </el>
+  <el>
+    <u>7</u>
+  </el>
+  <el>
+    <u>8</u>
+  </el>
+  <el>
+    <u>9</u>
+  </el>
+  </A>
+</tplxml>
diff --git a/libs/libtpl-1.5/lang/perl/tests/test11 b/libs/libtpl-1.5/lang/perl/tests/test11
new file mode 100755 (executable)
index 0000000..1198015
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my $i;
+my $tpl = Tpl->tpl_map("B",\$i);
+$i = pack("CCCC", 0xA, 0xB, 0xC, 0xD);
+$tpl->tpl_pack(0); 
+$tpl->tpl_dump($tmp1);
+
+
+$tpl = Tpl->tpl_map("B",\$i);
+$tpl->tpl_load($tmp1);
+$tpl->tpl_unpack(0);
+print "$i\n";
diff --git a/libs/libtpl-1.5/lang/perl/tests/test11.ans b/libs/libtpl-1.5/lang/perl/tests/test11.ans
new file mode 100755 (executable)
index 0000000..b04dd2e
--- /dev/null
@@ -0,0 +1,2 @@
+
+\v\f\r
diff --git a/libs/libtpl-1.5/lang/perl/tests/test12 b/libs/libtpl-1.5/lang/perl/tests/test12
new file mode 100755 (executable)
index 0000000..4dfed01
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my $i;
+my $tpl = Tpl->tpl_map("A(f)",\$i);
+for($i=0; $i<10.0; $i+=2/3.0) { $tpl->tpl_pack(1); }
+$tpl->tpl_dump($tmp1);
+
+my $j;
+my $tpl2 = Tpl->tpl_map("A(f)",\$j);
+$tpl2->tpl_load($tmp1);
+while($tpl2->tpl_unpack(1) > 0) { printf("%.6f\n", $j); }
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test12.ans b/libs/libtpl-1.5/lang/perl/tests/test12.ans
new file mode 100755 (executable)
index 0000000..3849b4f
--- /dev/null
@@ -0,0 +1,16 @@
+0.000000
+0.666667
+1.333333
+2.000000
+2.666667
+3.333333
+4.000000
+4.666667
+5.333333
+6.000000
+6.666667
+7.333333
+8.000000
+8.666667
+9.333333
+10.000000
diff --git a/libs/libtpl-1.5/lang/perl/tests/test13 b/libs/libtpl-1.5/lang/perl/tests/test13
new file mode 100755 (executable)
index 0000000..65f2c37
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $i;
+my $tpl = Tpl->tpl_map("A(f)",\$i);
+for($i=0; $i<10.0; $i+=2/3.0) { $tpl->tpl_pack(1); }
+my $img = $tpl->tpl_dump();
+
+open TPLXML, "|../tplxml" or die "can't open tplxml: $!";
+print TPLXML $img;
+close TPLXML;
diff --git a/libs/libtpl-1.5/lang/perl/tests/test13.ans b/libs/libtpl-1.5/lang/perl/tests/test13.ans
new file mode 100755 (executable)
index 0000000..f8b97db
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" ?>
+      <!DOCTYPE tplxml [ 
+      <!ELEMENT tplxml (A|i|u|I|U|B|s|c|f|fx)*>
+      <!ATTLIST tplxml
+         format CDATA #REQUIRED
+         fxlens CDATA #REQUIRED
+      >
+      <!ELEMENT i (#PCDATA)>
+      <!ELEMENT u (#PCDATA)>
+      <!ELEMENT I (#PCDATA)>
+      <!ELEMENT U (#PCDATA)>
+      <!ELEMENT B (#PCDATA)>
+      <!ELEMENT s (#PCDATA)>
+      <!ELEMENT c (#PCDATA)>
+      <!ELEMENT f (#PCDATA)>
+      <!ELEMENT A (el)*>
+      <!ELEMENT el (A|i|u|I|U|B|s|c|f|fx)+>
+      <!ELEMENT fx (i|u|I|U|c|f)*>
+      ]>
+<tplxml format="A(f)" fxlens="">
+  <A>
+  <el>
+    <f>0</f>
+  </el>
+  <el>
+    <f>0.666666666666667</f>
+  </el>
+  <el>
+    <f>1.33333333333333</f>
+  </el>
+  <el>
+    <f>2</f>
+  </el>
+  <el>
+    <f>2.66666666666667</f>
+  </el>
+  <el>
+    <f>3.33333333333333</f>
+  </el>
+  <el>
+    <f>4</f>
+  </el>
+  <el>
+    <f>4.66666666666667</f>
+  </el>
+  <el>
+    <f>5.33333333333333</f>
+  </el>
+  <el>
+    <f>6</f>
+  </el>
+  <el>
+    <f>6.66666666666667</f>
+  </el>
+  <el>
+    <f>7.33333333333333</f>
+  </el>
+  <el>
+    <f>8</f>
+  </el>
+  <el>
+    <f>8.66666666666667</f>
+  </el>
+  <el>
+    <f>9.33333333333333</f>
+  </el>
+  <el>
+    <f>10</f>
+  </el>
+  </A>
+</tplxml>
diff --git a/libs/libtpl-1.5/lang/perl/tests/test14 b/libs/libtpl-1.5/lang/perl/tests/test14
new file mode 100755 (executable)
index 0000000..920bd80
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $tmp1 = "test14.tpl";
+
+my $j;
+my $tpl2 = Tpl->tpl_map("i",\$j);
+$tpl2->tpl_load($tmp1);
+$tpl2->tpl_unpack(0);
+print "$j\n";
+
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test14.ans b/libs/libtpl-1.5/lang/perl/tests/test14.ans
new file mode 100755 (executable)
index 0000000..3fbedf6
--- /dev/null
@@ -0,0 +1 @@
+-2
diff --git a/libs/libtpl-1.5/lang/perl/tests/test14.tpl b/libs/libtpl-1.5/lang/perl/tests/test14.tpl
new file mode 100755 (executable)
index 0000000..f11ee5f
Binary files /dev/null and b/libs/libtpl-1.5/lang/perl/tests/test14.tpl differ
diff --git a/libs/libtpl-1.5/lang/perl/tests/test15 b/libs/libtpl-1.5/lang/perl/tests/test15
new file mode 100755 (executable)
index 0000000..e65437d
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $tmp1 = "test15.tpl";
+
+my $j;
+my $tpl2 = Tpl->tpl_map("i",\$j);
+$tpl2->tpl_load($tmp1);
+$tpl2->tpl_unpack(0);
+print "$j\n";
+
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test15.ans b/libs/libtpl-1.5/lang/perl/tests/test15.ans
new file mode 100755 (executable)
index 0000000..a83d1d5
--- /dev/null
@@ -0,0 +1 @@
+-3
diff --git a/libs/libtpl-1.5/lang/perl/tests/test15.tpl b/libs/libtpl-1.5/lang/perl/tests/test15.tpl
new file mode 100755 (executable)
index 0000000..69249f7
Binary files /dev/null and b/libs/libtpl-1.5/lang/perl/tests/test15.tpl differ
diff --git a/libs/libtpl-1.5/lang/perl/tests/test16 b/libs/libtpl-1.5/lang/perl/tests/test16
new file mode 100755 (executable)
index 0000000..2d24fc7
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $i;
+my $tpl = Tpl->tpl_map("B",\$i);
+$i = pack("CCCC", 0xA, 0xB, 0xC, 0xD);
+$tpl->tpl_pack(0); 
+my $img = $tpl->tpl_dump();
+
+
+$tpl = Tpl->tpl_map("B",\$i);
+$tpl->tpl_load(\$img);
+$tpl->tpl_unpack(0);
+print "$i\n";
diff --git a/libs/libtpl-1.5/lang/perl/tests/test16.ans b/libs/libtpl-1.5/lang/perl/tests/test16.ans
new file mode 100755 (executable)
index 0000000..b04dd2e
--- /dev/null
@@ -0,0 +1,2 @@
+
+\v\f\r
diff --git a/libs/libtpl-1.5/lang/perl/tests/test17 b/libs/libtpl-1.5/lang/perl/tests/test17
new file mode 100755 (executable)
index 0000000..18ab7d8
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my ($i,$j)=(1,ord('a'));
+my $tpl = Tpl->tpl_map("S(ic)",\$i, \$j);
+$tpl->tpl_pack(0);
+$tpl->tpl_dump($tmp1);
+
+($i,$j)=(-9,"x");
+my $tpl2 = Tpl->tpl_map("S(ic)",\$i,\$j);
+$tpl2->tpl_load($tmp1);
+$tpl2->tpl_unpack(0);
+$j = chr($j);
+print "$i,$j\n"; 
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test17.ans b/libs/libtpl-1.5/lang/perl/tests/test17.ans
new file mode 100755 (executable)
index 0000000..a441d18
--- /dev/null
@@ -0,0 +1 @@
+1,a
diff --git a/libs/libtpl-1.5/lang/perl/tests/test18 b/libs/libtpl-1.5/lang/perl/tests/test18
new file mode 100755 (executable)
index 0000000..e6f8e04
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my @i=(1,2,3,4);
+my $tpl = Tpl->tpl_map("i#",\@i, 3);
+$tpl->tpl_pack(0);
+$tpl->tpl_dump($tmp1);
+
+my @j;
+my $tpl2 = Tpl->tpl_map("i#",\@j,3);
+$tpl2->tpl_load($tmp1);
+$tpl2->tpl_unpack(0);
+print "$_\n" for @j;
diff --git a/libs/libtpl-1.5/lang/perl/tests/test18.ans b/libs/libtpl-1.5/lang/perl/tests/test18.ans
new file mode 100755 (executable)
index 0000000..01e79c3
--- /dev/null
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/libs/libtpl-1.5/lang/perl/tests/test19 b/libs/libtpl-1.5/lang/perl/tests/test19
new file mode 100755 (executable)
index 0000000..79e8b00
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my @i=(1,2,3,4);
+my @j=(-1,-2,-3, -4);
+my $tpl = Tpl->tpl_map("i#i#",\@i, 3, \@j, 4);
+$tpl->tpl_pack(0);
+$tpl->tpl_dump($tmp1);
+
+my (@x,@y);
+my $tpl2 = Tpl->tpl_map("i#i#",\@x, 3, \@y, 4);
+$tpl2->tpl_load($tmp1);
+$tpl2->tpl_unpack(0);
+print "$_\n" for @x;
+print "$_\n" for @y;
diff --git a/libs/libtpl-1.5/lang/perl/tests/test19.ans b/libs/libtpl-1.5/lang/perl/tests/test19.ans
new file mode 100755 (executable)
index 0000000..eee553c
--- /dev/null
@@ -0,0 +1,7 @@
+1
+2
+3
+-1
+-2
+-3
+-4
diff --git a/libs/libtpl-1.5/lang/perl/tests/test2 b/libs/libtpl-1.5/lang/perl/tests/test2
new file mode 100755 (executable)
index 0000000..e552cf7
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+my $img = $tpl->tpl_dump();
+
+my $j;
+my $tpl2 = Tpl->tpl_map("A(i)",\$j);
+$tpl2->tpl_load(\$img);
+while($tpl2->tpl_unpack(1) > 0) { print "$j\n" }
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test2.ans b/libs/libtpl-1.5/lang/perl/tests/test2.ans
new file mode 100755 (executable)
index 0000000..8b1acc1
--- /dev/null
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/libs/libtpl-1.5/lang/perl/tests/test20 b/libs/libtpl-1.5/lang/perl/tests/test20
new file mode 100755 (executable)
index 0000000..e78edc7
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+my $tmp2 = "$pwd/$0_2.out";
+my $tmp3 = "$pwd/$0_3.out";
+
+my ($c,@i);
+my $tpl = Tpl->tpl_map("A(S(ci#))",\$c,\@i,10);
+
+# make element 1
+$c = 97;
+@i = (0,1,2,3,4,5,6,7,8,9);
+$tpl->tpl_pack(1);
+
+# make element 2
+$c = 98;
+@i = (1,2,3,4,5,6,7,8,9,10);
+$tpl->tpl_pack(1);
+
+$tpl->tpl_dump($tmp1);
+
+
+`../tplxml $tmp1 > $tmp2`;        # convert tpl to xml
+`../tplxml $tmp2 > $tmp3`;        # convert xml back to tpl
+`diff $tmp1 $tmp3`;
+print "tpl files ", ($? ? "differ" : "identical"), "\n";
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test20.ans b/libs/libtpl-1.5/lang/perl/tests/test20.ans
new file mode 100755 (executable)
index 0000000..1d74042
--- /dev/null
@@ -0,0 +1 @@
+tpl files identical
diff --git a/libs/libtpl-1.5/lang/perl/tests/test21 b/libs/libtpl-1.5/lang/perl/tests/test21
new file mode 100755 (executable)
index 0000000..814ff1f
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+my $img = $tpl->tpl_dump();
+
+my $fmt = Tpl->tpl_peek(\$img);
+print("$fmt\n");
diff --git a/libs/libtpl-1.5/lang/perl/tests/test21.ans b/libs/libtpl-1.5/lang/perl/tests/test21.ans
new file mode 100755 (executable)
index 0000000..bc9aa33
--- /dev/null
@@ -0,0 +1 @@
+A(i)
diff --git a/libs/libtpl-1.5/lang/perl/tests/test22 b/libs/libtpl-1.5/lang/perl/tests/test22
new file mode 100755 (executable)
index 0000000..416978f
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my @i=(1,2,3,4);
+my @j=(-1,-2,-3, -4);
+my $tpl = Tpl->tpl_map("i#i#",\@i, 3, \@j, 4);
+$tpl->tpl_pack(0);
+$tpl->tpl_dump($tmp1);
+
+my $fmt = Tpl->tpl_peek($tmp1);
+print "$fmt\n";
diff --git a/libs/libtpl-1.5/lang/perl/tests/test22.ans b/libs/libtpl-1.5/lang/perl/tests/test22.ans
new file mode 100755 (executable)
index 0000000..7dd3f3f
--- /dev/null
@@ -0,0 +1 @@
+i#i#
diff --git a/libs/libtpl-1.5/lang/perl/tests/test23 b/libs/libtpl-1.5/lang/perl/tests/test23
new file mode 100755 (executable)
index 0000000..13c67e9
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+# this test only works on 64-bit Perl
+
+my ($i,$j) = (-4294967296,4294967296); # 2^32 (can't fit in a 32-bit value)
+my $tpl = Tpl->tpl_map("IU",\$i,\$j);
+$tpl->tpl_pack(0); 
+my $img = $tpl->tpl_dump();
+
+my ($x,$y);
+my $tpl2 = Tpl->tpl_map("IU",\$x,\$y);
+$tpl2->tpl_load(\$img);
+$tpl2->tpl_unpack(0);
+print "$x $y\n";
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test3 b/libs/libtpl-1.5/lang/perl/tests/test3
new file mode 100755 (executable)
index 0000000..9bbc0b1
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+my $img = $tpl->tpl_dump();
+
+open TPLXML, "|../tplxml" or die "can't open tplxml: $!";
+print TPLXML $img;
+close TPLXML;
diff --git a/libs/libtpl-1.5/lang/perl/tests/test3.ans b/libs/libtpl-1.5/lang/perl/tests/test3.ans
new file mode 100755 (executable)
index 0000000..4399a64
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" ?>
+      <!DOCTYPE tplxml [ 
+      <!ELEMENT tplxml (A|i|u|I|U|B|s|c|f|fx)*>
+      <!ATTLIST tplxml
+         format CDATA #REQUIRED
+         fxlens CDATA #REQUIRED
+      >
+      <!ELEMENT i (#PCDATA)>
+      <!ELEMENT u (#PCDATA)>
+      <!ELEMENT I (#PCDATA)>
+      <!ELEMENT U (#PCDATA)>
+      <!ELEMENT B (#PCDATA)>
+      <!ELEMENT s (#PCDATA)>
+      <!ELEMENT c (#PCDATA)>
+      <!ELEMENT f (#PCDATA)>
+      <!ELEMENT A (el)*>
+      <!ELEMENT el (A|i|u|I|U|B|s|c|f|fx)+>
+      <!ELEMENT fx (i|u|I|U|c|f)*>
+      ]>
+<tplxml format="A(i)" fxlens="">
+  <A>
+  <el>
+    <i>0</i>
+  </el>
+  <el>
+    <i>1</i>
+  </el>
+  <el>
+    <i>2</i>
+  </el>
+  <el>
+    <i>3</i>
+  </el>
+  <el>
+    <i>4</i>
+  </el>
+  <el>
+    <i>5</i>
+  </el>
+  <el>
+    <i>6</i>
+  </el>
+  <el>
+    <i>7</i>
+  </el>
+  <el>
+    <i>8</i>
+  </el>
+  <el>
+    <i>9</i>
+  </el>
+  </A>
+</tplxml>
diff --git a/libs/libtpl-1.5/lang/perl/tests/test4 b/libs/libtpl-1.5/lang/perl/tests/test4
new file mode 100755 (executable)
index 0000000..2a71a25
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+my $tmp2 = "$pwd/$0_2.out";
+my $tmp3 = "$pwd/$0_3.out";
+
+my $i;
+my $tpl = Tpl->tpl_map("A(i)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+$tpl->tpl_dump($tmp1);
+
+
+`../tplxml $tmp1 > $tmp2`;        # convert tpl to xml
+`../tplxml $tmp2 > $tmp3`;        # convert xml back to tpl
+`diff $tmp1 $tmp3`;
+print "tpl files ", ($? ? "differ" : "identical"), "\n";
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test4.ans b/libs/libtpl-1.5/lang/perl/tests/test4.ans
new file mode 100755 (executable)
index 0000000..1d74042
--- /dev/null
@@ -0,0 +1 @@
+tpl files identical
diff --git a/libs/libtpl-1.5/lang/perl/tests/test5 b/libs/libtpl-1.5/lang/perl/tests/test5
new file mode 100755 (executable)
index 0000000..0638503
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my $i;
+my $tpl = Tpl->tpl_map("A(c)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+$tpl->tpl_dump($tmp1);
+
+my $j;
+my $tpl2 = Tpl->tpl_map("A(c)",\$j);
+$tpl2->tpl_load($tmp1);
+while($tpl2->tpl_unpack(1) > 0) { printf("%d\n", $j); }
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test5.ans b/libs/libtpl-1.5/lang/perl/tests/test5.ans
new file mode 100755 (executable)
index 0000000..8b1acc1
--- /dev/null
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/libs/libtpl-1.5/lang/perl/tests/test6 b/libs/libtpl-1.5/lang/perl/tests/test6
new file mode 100755 (executable)
index 0000000..595a800
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $i;
+my $tpl = Tpl->tpl_map("A(c)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+my $img = $tpl->tpl_dump();
+
+open TPLXML, "|../tplxml" or die "can't open tplxml: $!";
+print TPLXML $img;
+close TPLXML;
diff --git a/libs/libtpl-1.5/lang/perl/tests/test6.ans b/libs/libtpl-1.5/lang/perl/tests/test6.ans
new file mode 100755 (executable)
index 0000000..a84432e
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" ?>
+      <!DOCTYPE tplxml [ 
+      <!ELEMENT tplxml (A|i|u|I|U|B|s|c|f|fx)*>
+      <!ATTLIST tplxml
+         format CDATA #REQUIRED
+         fxlens CDATA #REQUIRED
+      >
+      <!ELEMENT i (#PCDATA)>
+      <!ELEMENT u (#PCDATA)>
+      <!ELEMENT I (#PCDATA)>
+      <!ELEMENT U (#PCDATA)>
+      <!ELEMENT B (#PCDATA)>
+      <!ELEMENT s (#PCDATA)>
+      <!ELEMENT c (#PCDATA)>
+      <!ELEMENT f (#PCDATA)>
+      <!ELEMENT A (el)*>
+      <!ELEMENT el (A|i|u|I|U|B|s|c|f|fx)+>
+      <!ELEMENT fx (i|u|I|U|c|f)*>
+      ]>
+<tplxml format="A(c)" fxlens="">
+  <A>
+  <el>
+    <c>0</c>
+  </el>
+  <el>
+    <c>1</c>
+  </el>
+  <el>
+    <c>2</c>
+  </el>
+  <el>
+    <c>3</c>
+  </el>
+  <el>
+    <c>4</c>
+  </el>
+  <el>
+    <c>5</c>
+  </el>
+  <el>
+    <c>6</c>
+  </el>
+  <el>
+    <c>7</c>
+  </el>
+  <el>
+    <c>8</c>
+  </el>
+  <el>
+    <c>9</c>
+  </el>
+  </A>
+</tplxml>
diff --git a/libs/libtpl-1.5/lang/perl/tests/test7 b/libs/libtpl-1.5/lang/perl/tests/test7
new file mode 100755 (executable)
index 0000000..b6b0850
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+my $tmp2 = "$pwd/$0_2.out";
+my $tmp3 = "$pwd/$0_3.out";
+
+my $i;
+my $tpl = Tpl->tpl_map("A(c)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+$tpl->tpl_dump($tmp1);
+
+
+`../tplxml $tmp1 > $tmp2`;        # convert tpl to xml
+`../tplxml $tmp2 > $tmp3`;        # convert xml back to tpl
+`diff $tmp1 $tmp3`;
+print "tpl files ", ($? ? "differ" : "identical"), "\n";
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test7.ans b/libs/libtpl-1.5/lang/perl/tests/test7.ans
new file mode 100755 (executable)
index 0000000..1d74042
--- /dev/null
@@ -0,0 +1 @@
+tpl files identical
diff --git a/libs/libtpl-1.5/lang/perl/tests/test8 b/libs/libtpl-1.5/lang/perl/tests/test8
new file mode 100755 (executable)
index 0000000..f6c194f
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+my $tmp2 = "$pwd/$0_2.out";
+my $tmp3 = "$pwd/$0_3.out";
+
+my $i;
+my $tpl = Tpl->tpl_map("A(s)",\$i);
+for (qw(normal has&ampersand <anglebrackets>)) { 
+    $i = $_; 
+    $tpl->tpl_pack(1); 
+}
+$tpl->tpl_dump($tmp1);
+
+
+`../tplxml $tmp1 > $tmp2`;        # convert tpl to xml
+`../tplxml $tmp2 > $tmp3`;        # convert xml back to tpl
+`diff $tmp1 $tmp3`;
+print "tpl files ", ($? ? "differ" : "identical"), "\n";
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test8.ans b/libs/libtpl-1.5/lang/perl/tests/test8.ans
new file mode 100755 (executable)
index 0000000..1d74042
--- /dev/null
@@ -0,0 +1 @@
+tpl files identical
diff --git a/libs/libtpl-1.5/lang/perl/tests/test9 b/libs/libtpl-1.5/lang/perl/tests/test9
new file mode 100755 (executable)
index 0000000..75ec15e
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+#
+use  strict;
+use warnings;
+
+use lib "..";
+use Tpl;
+
+my $pwd = `pwd`;
+chomp $pwd;
+
+my $tmp1 = "$pwd/$0_1.out";
+
+my $i;
+my $tpl = Tpl->tpl_map("A(u)",\$i);
+for($i=0; $i<10; $i++) { $tpl->tpl_pack(1); }
+$tpl->tpl_dump($tmp1);
+
+my $j;
+my $tpl2 = Tpl->tpl_map("A(u)",\$j);
+$tpl2->tpl_load($tmp1);
+while($tpl2->tpl_unpack(1) > 0) { print "$j\n" }
+
diff --git a/libs/libtpl-1.5/lang/perl/tests/test9.ans b/libs/libtpl-1.5/lang/perl/tests/test9.ans
new file mode 100755 (executable)
index 0000000..8b1acc1
--- /dev/null
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/libs/libtpl-1.5/lang/perl/tplfmt b/libs/libtpl-1.5/lang/perl/tplfmt
new file mode 100755 (executable)
index 0000000..b3b0603
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+
+# tplfmt 
+# by Troy Hanson  Feb 2006
+# print the format string of a tpl image file 
+
+use strict;
+use warnings;
+
+sub peek_fmt {
+    my $buf = shift;
+    die "invalid tpl file" unless ($$buf =~ /^tpl/);
+    return (unpack("Z*", substr($$buf,8)));
+}
+
+die "usage: $0 <file> [<file> ...]" unless (@ARGV > 0);
+
+undef $/; # slurp
+for (@ARGV) {
+    open TPL, "<$_" or die "can't open $_: $!";
+    my $tpl = <TPL>;
+    print "$_: ", peek_fmt(\$tpl), "\n";
+    close TPL;
+}
diff --git a/libs/libtpl-1.5/lang/perl/tplxml b/libs/libtpl-1.5/lang/perl/tplxml
new file mode 100755 (executable)
index 0000000..5037dc3
--- /dev/null
@@ -0,0 +1,306 @@
+#!/usr/bin/perl
+
+# tplxml 
+# by Troy Hanson   27 Feb 2006
+# convert between tpl and XML
+
+# Copyright (c) 2005-2006, Troy Hanson     http://tpl.sourceforge.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:
+# 
+#   * 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.
+#   * Neither the name of the copyright holder nor the names of its
+#     contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+# 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.
+
+use strict;
+use warnings;
+use XML::Parser;
+use FindBin;
+use lib "$FindBin::Bin";  #locate Tpl.pm in same directory as tplxml
+use Tpl;
+use bytes;
+
+sub quote_chars {
+    my $str = shift;
+    $$str =~ s/&/&amp;/g;  #order matters
+    $$str =~ s/</&lt;/g;
+    $$str =~ s/>/&gt;/g;
+}
+sub unquote_chars {
+    my $str = shift;
+    $$str =~ s/&lt;/</g;
+    $$str =~ s/&gt;/>/g;
+    $$str =~ s/&amp;/&/g;
+}
+sub hex_chars {
+    my $str = shift;
+    my $hex;
+    for(my $i=0; $i < length $$str; $i++) {
+        my $byte = unpack("C",substr($$str,$i,1));
+        $hex .= sprintf("%02x", $byte);
+    }
+    $$str = $hex;
+}
+sub unhex_chars {
+    my $str = shift;
+    my $bytes;
+    for(my $i=0; $i < length $$str; $i+=2) {
+        my $hexbyte = substr($$str,$i,2);
+        $bytes .= pack("C", hex($hexbyte));
+    }
+    $$str= $bytes;
+}
+
+sub tpl2xml {
+    my $src = shift;
+    my (@out,@args);
+
+    # build list of references to hold output of unpacking
+    my ($fmt,@fxlens) = peek_fmt($src);
+    for(my ($i,$j,$k)=(0,0,0);$i<length($fmt);$i++) {
+        push @args, [] if substr($fmt,$i,2) =~ /^[iucfIU]\#$/; # octothorpic
+        push @args, \$out[$j++] if substr($fmt,$i,2) =~ /^[iuBscfIU][^\#]*$/;
+        push @args, $fxlens[$k++] if substr($fmt,$i,1) eq "#";
+    }
+
+    my $tpl = Tpl->tpl_map($fmt,@args);
+    $tpl->tpl_load($src);
+    $tpl->tpl_unpack(0);
+
+    # construct xml preamble
+    my $pre = qq{<?xml version="1.0" encoding="utf-8" ?>
+      <!DOCTYPE tplxml [ 
+      <!ELEMENT tplxml (A|i|u|I|U|B|s|c|f|fx)*>
+      <!ATTLIST tplxml
+         format CDATA #REQUIRED
+         fxlens CDATA #REQUIRED
+      >
+      <!ELEMENT i (#PCDATA)>
+      <!ELEMENT u (#PCDATA)>
+      <!ELEMENT I (#PCDATA)>
+      <!ELEMENT U (#PCDATA)>
+      <!ELEMENT B (#PCDATA)>
+      <!ELEMENT s (#PCDATA)>
+      <!ELEMENT c (#PCDATA)>
+      <!ELEMENT f (#PCDATA)>
+      <!ELEMENT A (el)*>
+      <!ELEMENT el (A|i|u|I|U|B|s|c|f|fx)+>
+      <!ELEMENT fx (i|u|I|U|c|f)*>
+      ]>\n};
+    print $pre;
+    my $fxattr = join ",", @fxlens;
+    print qq{<tplxml format="$fmt" fxlens="$fxattr">\n};
+    tpl2xml_node($tpl,"A0",1);
+    print qq{</tplxml>\n};
+}
+
+sub tpl2xml_node {
+    my $tpl = shift;
+    my $node = shift;
+    my $indent = shift;
+    my $i = "  " x $indent;
+    for my $c (@{ $tpl->{$node} }) {
+        if (ref($c)) { 
+            my ($type,$addr,$fxlen) = @$c;
+            quote_chars $addr if $type eq 's';
+            hex_chars $addr if $type eq 'B';
+            if (not defined $fxlen) {
+                print qq{$i<$type>$$addr</$type>\n}; # singleton
+            } else {
+                # all elements of octothorpic fixed-len array
+                print qq{$i<fx>\n};
+                print qq{$i  <$type>$addr->[$_]</$type>\n} for (0..$fxlen-1); 
+                print qq{$i</fx>\n};
+            }
+        } else { 
+            # A node
+            print qq{$i<A>\n};
+            my $idx = $1 if $c =~ /^A(\d+)$/;
+            while($tpl->tpl_unpack($idx) > 0) {
+                print qq{$i<el>\n};
+                tpl2xml_node($tpl,$c,$indent+1);  
+                print qq{$i</el>\n};
+            }
+            print qq{$i</A>\n};
+        }
+    }
+}
+
+sub xml2tpl {
+    my $src = shift;
+    my $p = new XML::Parser( Style => 'Tree' );
+    my $tree = $p->parse($$src); 
+    die "not a tpl xml document" unless $tree->[0] eq 'tplxml';
+    die "no format attribute" unless defined $tree->[1][0]->{format};
+    my $fmt = $tree->[1][0]->{format};
+    die "no fxlens attribute" unless defined $tree->[1][0]->{fxlens};
+    my @fxlens = split /,/, $tree->[1][0]->{fxlens};
+
+    # build list of references to variables for use in packing
+    my (@args,@out);
+    for(my ($i,$j,$k)=(0,0,0);$i<length($fmt);$i++) {
+        push @args, [] if substr($fmt,$i,2) =~ /^[iucfIU]\#$/; # octothorpic
+        push @args, \$out[$j++] if substr($fmt,$i,2) =~ /^[iuBscfIU][^\#]*$/;
+        push @args, $fxlens[$k++] if substr($fmt,$i,1) eq "#";
+    }
+
+    my $tpl = Tpl->tpl_map($fmt,@args);
+    xml2tpl_dfs($tpl,$tree->[1]);
+    $tpl->tpl_pack(0);
+    print $tpl->tpl_dump;
+}
+
+sub xml2tpl_dfs {
+    my $tpl = shift;
+    my $xml = shift;
+
+    my @next = @$xml;  # ($attr,@tagvals) = $$xml;
+    shift @next;  # discard <tplxml> attributes
+    my @tpltoks = @{ $tpl->{"A0"} }; #expected tokens when parsing
+    
+    TAG: while (@next) {
+        my $xmltag = shift @next;
+        my $xmlval = shift @next;
+
+        # skip whitespace/newlines embedded between tags
+        next TAG if ($xmltag eq "0" and $xmlval =~ /^\s+$/); 
+
+        # pack if necessary. consume tokens by look-ahead until non-pack token.
+        while (@tpltoks > 0 and $tpltoks[0] =~ /^P(\d+)$/) {
+            shift @tpltoks;
+            $tpl->tpl_pack($1);
+        }
+
+        # If tpl format specifies a non-array type should appear at this point 
+        # in the XML tree, then validate the type matches the format and assign 
+        # the value from the XML to the variable from which it'll be packed
+        my $tpltoken = shift @tpltoks;
+        my $octothorpic=0;
+        if (ref $tpltoken) {
+            my ($tpltype,$tpladdr,$fxlen) = @$tpltoken;
+
+            #  This block is how we handle octothorpic (fixed length) arrays.
+            #  If $fxlen is defined then an octothorpic <fx> node is expected.
+            #  After finding the <fx> node we put its subnodes (the array elements)
+            #  onto the @next array for immediate parsing and we use $fxlen:$remaining
+            #  as a signet version of the $fxlen to induce the element-processing loop.
+            if (defined $fxlen) {
+                if ($fxlen =~ /^(\d+):(\d+)$/) { # $1==orig $fxlen, $2==remain $fxlen
+                    $octothorpic=1;
+                    unshift @tpltoks, [$tpltype, $tpladdr, $1.":".($2-1)] if $2 > 1;
+                } else { # octothorpic array expected; look for <fx> parent node
+                    die "expected '<fx>' but got '<$xmltag>'" unless $xmltag eq 'fx';
+                    @{ $tpladdr } = (); # Empty accumulator array for octothorpic values
+                    unshift @tpltoks, [$tpltype, $tpladdr, "$fxlen:$fxlen"]; # x:x signet
+                    shift @$xmlval; # discard 'A' attributes
+                    unshift @next, @$xmlval;  #parse xml subtree now (dfs)
+                    next TAG; # proceed to children of <fx> node
+                }
+            }
+
+            if ($tpltype ne $xmltag) {
+                die "mismatch: xml has '$xmltag' where format specifies '$tpltype'";
+            } 
+            # expect @$xmlval to be ({},0,'value') i.e. a single, terminal text node
+            if (@$xmlval > 3 || $xmlval->[1] ne '0') {
+                die "error: xml tag '$xmltag' cannot enclose sub-tags";
+            }
+            if ($octothorpic) {
+                push @{ $tpladdr }, $xmlval->[2]; 
+            } else {
+                $$tpladdr = $xmlval->[2]; 
+            }
+            unquote_chars $tpladdr if $tpltype eq 's';
+            unhex_chars $tpladdr if $tpltype eq 'B';
+        } elsif ($tpltoken =~ /^A(\d+)$/) {
+            # tpl format specifies an array should appear at this point in the XML
+            if ($xmltag ne 'A') {
+                die "mismatch: xml has '$xmltag' where format specifies 'A'";
+            }
+            shift @$xmlval; # discard 'A' attributes
+
+            # form token that means "replace me with tokens from A(n), x times"
+            # (where x is the number of elements contained by this array).
+            my $array_count=0;
+            for(my $i=0; $i < @$xmlval; $i+=2) {
+                $array_count++ if $xmlval->[$i] eq 'el';
+            }
+
+            unshift @tpltoks, "N$1:$array_count" if $array_count > 0; 
+            unshift @next, @$xmlval;  #parse xml subtree now (dfs)
+        } elsif ($tpltoken =~ /^N(\d+):(\d+)$/) {
+            if ($xmltag ne "el") {
+                die "mismatch: xml has '$xmltag' where array 'el' is expected";
+            }
+            # prepend A$1's tokens (and decremented N:count) to expected tokens 
+            my ($n,$elsleft) = ($1, ($2 - 1));
+            unshift @tpltoks, "N$n:$elsleft" if $elsleft > 0;  
+            unshift @tpltoks, "P$n";  # "pack me now" token
+            unshift @tpltoks, @{ $tpl->{"A$1"} };
+            
+            shift @$xmlval; # discard 'el' attributes
+            unshift @next, @$xmlval;  # proceed to parse el subtree (dfs)
+        } else {
+            die "internal error, unexpected token $tpltoken";
+        }
+    }
+
+    # pack if necessary. consume tokens by look-ahead until non-pack token.
+    while (@tpltoks > 0 and $tpltoks[0] =~ /^P(\d+)$/) {
+        shift @tpltoks;
+        $tpl->tpl_pack($1);
+    }
+
+    if (@tpltoks > 0) {
+        die "error: end of xml document reached but format requires more data";
+    }
+}
+
+sub peek_fmt {
+    my $buf = shift;
+    die "invalid tpl file" unless ($$buf =~ /^tpl/);
+    my $flags = CORE::unpack("C", substr($$buf,3,1));
+    my $UF = ($flags & 1) ? "N" : "V";  # big or little endian fxlens
+    my $fmt = (CORE::unpack("Z*", substr($$buf,8)));
+    my $num_octothorpes = scalar (my @o = ($fmt =~ /#/g));
+    my @fxlens;
+    my $fx = 8 + length($fmt) + 1;
+    for(my $i=0; $i < $num_octothorpes; $i++) {
+        my $fxlen_bytes = substr($$buf,$fx,4);
+        my $fxlen = unpack($UF, $fxlen_bytes);
+        push @fxlens, $fxlen;
+        $fx += 4;
+    }
+    return ($fmt,@fxlens);
+}
+
+##########################################################################
+# Slurp input file, auto-detect if conversion is to tpl or XML, and run.
+##########################################################################
+
+undef $/; 
+my $src = <>;
+our $to = (substr($src,0,3) eq "tpl") ? "xml" : "tpl";
+xml2tpl(\$src) if $to eq "tpl";
+tpl2xml(\$src) if $to eq "xml";
+
diff --git a/libs/libtpl-1.5/src/Makefile.am b/libs/libtpl-1.5/src/Makefile.am
new file mode 100755 (executable)
index 0000000..5719afc
--- /dev/null
@@ -0,0 +1,7 @@
+SUBDIRS = win
+lib_LTLIBRARIES = libtpl.la
+libtpl_la_SOURCES = tpl.c
+include_HEADERS = tpl.h
+libtpl_la_LDFLAGS = -no-undefined -version-info 0:0:0 
+libtpl_la_LIBADD = win/libwinmmap.la
+
diff --git a/libs/libtpl-1.5/src/Makefile.in b/libs/libtpl-1.5/src/Makefile.in
new file mode 100644 (file)
index 0000000..e38aed5
--- /dev/null
@@ -0,0 +1,607 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  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.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src
+DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libtpl_la_DEPENDENCIES = win/libwinmmap.la
+am_libtpl_la_OBJECTS = tpl.lo
+libtpl_la_OBJECTS = $(am_libtpl_la_OBJECTS)
+libtpl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(libtpl_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+SOURCES = $(libtpl_la_SOURCES)
+DIST_SOURCES = $(libtpl_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+       html-recursive info-recursive install-data-recursive \
+       install-dvi-recursive install-exec-recursive \
+       install-html-recursive install-info-recursive \
+       install-pdf-recursive install-ps-recursive install-recursive \
+       installcheck-recursive installdirs-recursive pdf-recursive \
+       ps-recursive uninstall-recursive
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(include_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = win
+lib_LTLIBRARIES = libtpl.la
+libtpl_la_SOURCES = tpl.c
+include_HEADERS = tpl.h
+libtpl_la_LDFLAGS = -no-undefined -version-info 0:0:0 
+libtpl_la_LIBADD = win/libwinmmap.la
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           f=$(am__strip_dir) \
+           echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+           $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+         else :; fi; \
+       done
+
+uninstall-libLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         p=$(am__strip_dir) \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+       done
+
+clean-libLTLIBRARIES:
+       -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+libtpl.la: $(libtpl_la_OBJECTS) $(libtpl_la_DEPENDENCIES) 
+       $(libtpl_la_LINK) -rpath $(libdir) $(libtpl_la_OBJECTS) $(libtpl_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tpl.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+install-includeHEADERS: $(include_HEADERS)
+       @$(NORMAL_INSTALL)
+       test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+       @list='$(include_HEADERS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
+         $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
+       done
+
+uninstall-includeHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(include_HEADERS)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
+         rm -f "$(DESTDIR)$(includedir)/$$f"; \
+       done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+       @failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+ctags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -d "$(distdir)/$$subdir" \
+           || $(MKDIR_P) "$(distdir)/$$subdir" \
+           || exit 1; \
+           distdir=`$(am__cd) $(distdir) && pwd`; \
+           top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+           (cd $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$top_distdir" \
+               distdir="$$distdir/$$subdir" \
+               am__remove_distdir=: \
+               am__skip_length_check=: \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+       for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+       mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-includeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+       install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+       all all-am check check-am clean clean-generic \
+       clean-libLTLIBRARIES clean-libtool ctags ctags-recursive \
+       distclean distclean-compile distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am \
+       install-includeHEADERS install-info install-info-am \
+       install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs installdirs-am maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags tags-recursive uninstall uninstall-am \
+       uninstall-includeHEADERS uninstall-libLTLIBRARIES
+
+# 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/libs/libtpl-1.5/src/tpl.c b/libs/libtpl-1.5/src/tpl.c
new file mode 100755 (executable)
index 0000000..24a9383
--- /dev/null
@@ -0,0 +1,2472 @@
+/*
+Copyright (c) 2005-2010, Troy D. Hanson     http://tpl.sourceforge.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:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+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.
+*/
+
+#define TPL_VERSION 1.5
+
+static const char id[]="$Id: tpl.c 192 2009-04-24 10:35:30Z thanson $";
+
+
+#include <stdlib.h>  /* malloc */
+#include <stdarg.h>  /* va_list */
+#include <string.h>  /* memcpy, memset, strchr */
+#include <stdio.h>   /* printf (tpl_hook.oops default function) */
+
+#ifndef _WIN32
+#include <unistd.h>     /* for ftruncate */
+#else
+#include <io.h>
+#define ftruncate(x,y) _chsize(x,y)
+#endif
+#include <sys/types.h>  /* for 'open' */
+#include <sys/stat.h>   /* for 'open' */
+#include <fcntl.h>      /* for 'open' */
+#include <errno.h>
+#ifndef _WIN32
+#include <inttypes.h>   /* uint32_t, uint64_t, etc */
+#else
+typedef unsigned short ushort;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#endif
+
+
+#if ( defined __CYGWIN__ || defined __MINGW32__ || defined _WIN32 )
+#include "win/mman.h"   /* mmap */
+#else
+#include <sys/mman.h>   /* mmap */
+#endif
+
+#include "tpl.h"
+
+#define TPL_GATHER_BUFLEN 8192
+#define TPL_MAGIC "tpl"
+
+/* macro to add a structure to a doubly-linked list */
+#define DL_ADD(head,add)                                        \
+    do {                                                        \
+        if (head) {                                             \
+            (add)->prev = (head)->prev;                         \
+            (head)->prev->next = (add);                         \
+            (head)->prev = (add);                               \
+            (add)->next = NULL;                                 \
+        } else {                                                \
+            (head)=(add);                                       \
+            (head)->prev = (head);                              \
+            (head)->next = NULL;                                \
+        }                                                       \
+    } while (0);
+
+#define fatal_oom() tpl_hook.fatal("out of memory\n")
+
+/* bit flags (internal). preceded by the external flags in tpl.h */
+#define TPL_WRONLY         (1 << 9)  /* app has initiated tpl packing  */
+#define TPL_RDONLY         (1 << 10)  /* tpl was loaded (for unpacking) */
+#define TPL_XENDIAN        (1 << 11)  /* swap endianness when unpacking */
+#define TPL_OLD_STRING_FMT (1 << 12) /* tpl has strings in 1.2 format */
+
+/* values for the flags byte that appears after the magic prefix */
+#define TPL_SUPPORTED_BITFLAGS 3
+#define TPL_FL_BIGENDIAN   (1 << 0)
+#define TPL_FL_NULLSTRINGS (1 << 1)
+
+/* char values for node type */
+#define TPL_TYPE_ROOT   0
+#define TPL_TYPE_INT32  1
+#define TPL_TYPE_UINT32 2
+#define TPL_TYPE_BYTE   3
+#define TPL_TYPE_STR    4
+#define TPL_TYPE_ARY    5
+#define TPL_TYPE_BIN    6
+#define TPL_TYPE_DOUBLE 7
+#define TPL_TYPE_INT64  8
+#define TPL_TYPE_UINT64 9
+#define TPL_TYPE_INT16  10
+#define TPL_TYPE_UINT16 11
+#define TPL_TYPE_POUND  12
+
+/* error codes */
+#define ERR_NOT_MINSIZE        (-1)
+#define ERR_MAGIC_MISMATCH     (-2)
+#define ERR_INCONSISTENT_SZ    (-3)
+#define ERR_FMT_INVALID        (-4)
+#define ERR_FMT_MISSING_NUL    (-5)
+#define ERR_FMT_MISMATCH       (-6)
+#define ERR_FLEN_MISMATCH      (-7)
+#define ERR_INCONSISTENT_SZ2   (-8)
+#define ERR_INCONSISTENT_SZ3   (-9)
+#define ERR_INCONSISTENT_SZ4   (-10)
+#define ERR_UNSUPPORTED_FLAGS  (-11)
+
+/* access to A(...) nodes by index */
+typedef struct tpl_pidx {
+    struct tpl_node *node;
+    struct tpl_pidx *next,*prev;
+} tpl_pidx;
+
+/* A(...) node datum */
+typedef struct tpl_atyp {
+    uint32_t num;    /* num elements */
+    size_t sz;       /* size of each backbone's datum */
+    struct tpl_backbone *bb,*bbtail; 
+    void *cur;                       
+} tpl_atyp;
+
+/* backbone to extend A(...) lists dynamically */
+typedef struct tpl_backbone {
+    struct tpl_backbone *next;
+    /* when this structure is malloc'd, extra space is alloc'd at the
+     * end to store the backbone "datum", and data points to it. */
+#if __STDC_VERSION__ < 199901
+    char *data;  
+#else
+    char data[];
+#endif
+} tpl_backbone;
+
+/* mmap record */
+typedef struct tpl_mmap_rec {
+    int fd;
+    void *text;
+    size_t text_sz;
+} tpl_mmap_rec;
+
+/* root node datum */
+typedef struct tpl_root_data {
+    int flags;
+    tpl_pidx *pidx;
+    tpl_mmap_rec mmap;
+    char *fmt;
+    int *fxlens, num_fxlens;
+} tpl_root_data;
+
+/* node type to size mapping */
+struct tpl_type_t {
+    char c;
+    int sz;
+};
+
+
+/* Internal prototypes */
+static tpl_node *tpl_node_new(tpl_node *parent);
+static tpl_node *tpl_find_i(tpl_node *n, int i);
+static void *tpl_cpv(void *datav, void *data, size_t sz);
+static void *tpl_extend_backbone(tpl_node *n);
+static char *tpl_fmt(tpl_node *r);
+static void *tpl_dump_atyp(tpl_node *n, tpl_atyp* at, void *dv);
+static size_t tpl_ser_osz(tpl_node *n);
+static void tpl_free_atyp(tpl_node *n,tpl_atyp *atyp);
+static int tpl_dump_to_mem(tpl_node *r, void *addr, size_t sz);
+static int tpl_mmap_file(char *filename, tpl_mmap_rec *map_rec);
+static int tpl_mmap_output_file(char *filename, size_t sz, void **text_out);
+static int tpl_cpu_bigendian(void);
+static int tpl_needs_endian_swap(void *);
+static void tpl_byteswap(void *word, int len);
+static void tpl_fatal(char *fmt, ...);
+static int tpl_serlen(tpl_node *r, tpl_node *n, void *dv, size_t *serlen);
+static int tpl_unpackA0(tpl_node *r);
+static int tpl_oops(const char *fmt, ...);
+static int tpl_gather_mem( char *buf, size_t len, tpl_gather_t **gs, tpl_gather_cb *cb, void *data);
+static int tpl_gather_nonblocking( int fd, tpl_gather_t **gs, tpl_gather_cb *cb, void *data);
+static int tpl_gather_blocking(int fd, void **img, size_t *sz);
+static tpl_node *tpl_map_va(char *fmt, va_list ap);
+
+/* This is used internally to help calculate padding when a 'double' 
+ * follows a smaller datatype in a structure. Normally under gcc
+ * on x86, d will be aligned at +4, however use of -malign-double
+ * causes d to be aligned at +8 (this is actually faster on x86).
+ * Also SPARC and x86_64 seem to align always on +8. 
+ */
+struct tpl_double_alignment_detector {
+    char a;
+    double d;  /* some platforms align this on +4, others on +8 */
+};
+
+/* this is another case where alignment varies. mac os x/gcc was observed
+ * to align the int64_t at +4 under -m32 and at +8 under -m64 */
+struct tpl_int64_alignment_detector {
+    int i;
+    int64_t j;  /* some platforms align this on +4, others on +8 */
+};
+
+typedef struct {
+  size_t inter_elt_len; /* padded inter-element len; i.e. &a[1].field - &a[0].field */
+  tpl_node *iter_start_node; /* node to jump back to, as we start each new iteration */
+  size_t iternum; /* current iteration number (total req'd. iter's in n->num) */
+} tpl_pound_data;
+
+/* Hooks for customizing tpl mem alloc, error handling, etc. Set defaults. */
+tpl_hook_t tpl_hook = {
+    /* .oops =       */ tpl_oops,
+    /* .malloc =     */ malloc,
+    /* .realloc =    */ realloc,
+    /* .free =       */ free,
+    /* .fatal =      */ tpl_fatal,
+    /* .gather_max = */ 0 /* max tpl size (bytes) for tpl_gather */
+};
+
+static const char tpl_fmt_chars[] = "AS($)BiucsfIUjv#"; /* valid format chars */
+static const char tpl_S_fmt_chars[] = "iucsfIUjv#$()"; /* valid within S(...) */
+static const char tpl_datapeek_ok_chars[] = "iucsfIUjv"; /* valid in datapeek */
+static const struct tpl_type_t tpl_types[] = {
+    /* [TPL_TYPE_ROOT] =   */  {'r', 0},
+    /* [TPL_TYPE_INT32] =  */  {'i', sizeof(int32_t)},
+    /* [TPL_TYPE_UINT32] = */  {'u', sizeof(uint32_t)},
+    /* [TPL_TYPE_BYTE] =   */  {'c', sizeof(char)},
+    /* [TPL_TYPE_STR] =    */  {'s', sizeof(char*)},
+    /* [TPL_TYPE_ARY] =    */  {'A', 0},
+    /* [TPL_TYPE_BIN] =    */  {'B', 0},
+    /* [TPL_TYPE_DOUBLE] = */  {'f', 8}, /* not sizeof(double) as that varies */
+    /* [TPL_TYPE_INT64] =  */  {'I', sizeof(int64_t)},
+    /* [TPL_TYPE_UINT64] = */  {'U', sizeof(uint64_t)},
+    /* [TPL_TYPE_INT16] =  */  {'j', sizeof(int16_t)},
+    /* [TPL_TYPE_UINT16] = */  {'v', sizeof(uint16_t)},
+    /* [TPL_TYPE_POUND] =  */  {'#', 0},
+};
+
+/* default error-reporting function. Just writes to stderr. */
+static int tpl_oops(const char *fmt, ...) {
+    va_list ap;
+    va_start(ap,fmt);
+    vfprintf(stderr,fmt,ap);
+    va_end(ap);
+    return 0;
+}
+
+
+static tpl_node *tpl_node_new(tpl_node *parent) {
+    tpl_node *n;
+    if ((n=tpl_hook.malloc(sizeof(tpl_node))) == NULL) {
+        fatal_oom();
+    }
+    n->addr=NULL;
+    n->data=NULL;
+    n->num=1;
+    n->ser_osz=0;
+    n->children=NULL;
+    n->next=NULL;
+    n->parent=parent;
+    return n;
+}
+
+/* Used in S(..) formats to pack several fields from a structure based on 
+ * only the structure address. We need to calculate field addresses 
+ * manually taking into account the size of the fields and intervening padding.
+ * The wrinkle is that double is not normally aligned on x86-32 but the
+ * -malign-double compiler option causes it to be. Double are aligned
+ * on Sparc, and apparently on 64 bit x86. We use a helper structure 
+ * to detect whether double is aligned in this compilation environment.
+ */
+char *calc_field_addr(tpl_node *parent, int type,char *struct_addr, int ordinal) {
+    tpl_node *prev;
+    int offset;
+    int align_sz;
+
+    if (ordinal == 1) return struct_addr;  /* first field starts on structure address */
+
+    /* generate enough padding so field addr is divisible by it's align_sz. 4, 8, etc */
+    prev = parent->children->prev; 
+    switch(type) {
+      case TPL_TYPE_DOUBLE:
+        align_sz = sizeof(struct tpl_double_alignment_detector) > 12 ? 8 : 4; 
+        break;
+      case TPL_TYPE_INT64:
+      case TPL_TYPE_UINT64:
+        align_sz = sizeof(struct tpl_int64_alignment_detector) > 12 ? 8 : 4; 
+        break;
+      default:
+        align_sz = tpl_types[type].sz;
+        break;
+    }
+    offset = ((uintptr_t)prev->addr - (uintptr_t)struct_addr)
+            + (tpl_types[prev->type].sz * prev->num);
+    offset = (offset + align_sz - 1) / align_sz * align_sz;
+    return struct_addr + offset;
+}
+
+TPL_API tpl_node *tpl_map(char *fmt,...) {
+  va_list ap;
+  tpl_node *tn;
+
+  va_start(ap,fmt);
+  tn = tpl_map_va(fmt, ap);
+  va_end(ap);
+  return tn;
+}
+
+static tpl_node *tpl_map_va(char *fmt, va_list ap) {
+    int lparen_level=0,expect_lparen=0,t=0,in_structure=0,ordinal=0;
+    int in_nested_structure=0;
+    char *c, *peek, *struct_addr=NULL, *struct_next;
+    tpl_node *root,*parent,*n=NULL,*preceding,*iter_start_node=NULL,
+             *struct_widest_node=NULL, *np; tpl_pidx *pidx;
+    tpl_pound_data *pd;
+    int *fxlens, num_fxlens, pound_num, pound_prod, applies_to_struct;
+    int contig_fxlens[10]; /* temp space for contiguous fxlens */
+    int num_contig_fxlens, i, j;
+    ptrdiff_t inter_elt_len=0; /* padded element length of contiguous structs in array */
+
+
+    root = tpl_node_new(NULL);
+    root->type = TPL_TYPE_ROOT; 
+    root->data = (tpl_root_data*)tpl_hook.malloc(sizeof(tpl_root_data));
+    if (!root->data) fatal_oom();
+    memset((tpl_root_data*)root->data,0,sizeof(tpl_root_data));
+
+    /* set up root nodes special ser_osz to reflect overhead of preamble */
+    root->ser_osz =  sizeof(uint32_t); /* tpl leading length */
+    root->ser_osz += strlen(fmt) + 1;  /* fmt + NUL-terminator */
+    root->ser_osz += 4;                /* 'tpl' magic prefix + flags byte */
+
+    parent=root;
+
+    c=fmt;
+    while (*c != '\0') {
+        switch (*c) {
+            case 'c':
+            case 'i':
+            case 'u':
+            case 'j':
+            case 'v':
+            case 'I':
+            case 'U':
+            case 'f':
+                if      (*c=='c') t=TPL_TYPE_BYTE;
+                else if (*c=='i') t=TPL_TYPE_INT32;
+                else if (*c=='u') t=TPL_TYPE_UINT32;
+                else if (*c=='j') t=TPL_TYPE_INT16;
+                else if (*c=='v') t=TPL_TYPE_UINT16;
+                else if (*c=='I') t=TPL_TYPE_INT64;
+                else if (*c=='U') t=TPL_TYPE_UINT64;
+                else if (*c=='f') t=TPL_TYPE_DOUBLE;
+
+                if (expect_lparen) goto fail;
+                n = tpl_node_new(parent);
+                n->type = t;
+                if (in_structure) {
+                    if (ordinal == 1) {
+                      /* for S(...)# iteration. Apply any changes to case 's' too!!! */
+                      iter_start_node = n; 
+                      struct_widest_node = n;
+                    }
+                    if (tpl_types[n->type].sz > tpl_types[struct_widest_node->type].sz) {
+                      struct_widest_node = n;
+                    }
+                    n->addr = calc_field_addr(parent,n->type,struct_addr,ordinal++);
+                } else n->addr = (void*)va_arg(ap,void*);
+                n->data = tpl_hook.malloc(tpl_types[t].sz);
+                if (!n->data) fatal_oom();
+                if (n->parent->type == TPL_TYPE_ARY) 
+                    ((tpl_atyp*)(n->parent->data))->sz += tpl_types[t].sz;
+                DL_ADD(parent->children,n);
+                break;
+            case 's':
+                if (expect_lparen) goto fail;
+                n = tpl_node_new(parent);
+                n->type = TPL_TYPE_STR;
+                if (in_structure) {
+                    if (ordinal == 1) {
+                      iter_start_node = n; /* for S(...)# iteration */
+                      struct_widest_node = n;
+                    }
+                    if (tpl_types[n->type].sz > tpl_types[struct_widest_node->type].sz) {
+                      struct_widest_node = n;
+                    }
+                    n->addr = calc_field_addr(parent,n->type,struct_addr,ordinal++);
+                } else n->addr = (void*)va_arg(ap,void*);
+                n->data = tpl_hook.malloc(sizeof(char*));
+                if (!n->data) fatal_oom();
+                *(char**)(n->data) = NULL;
+                if (n->parent->type == TPL_TYPE_ARY) 
+                    ((tpl_atyp*)(n->parent->data))->sz += sizeof(void*);
+                DL_ADD(parent->children,n);
+                break;
+            case '#':
+                /* apply a 'num' to preceding atom */
+                if (!parent->children) goto fail;
+                preceding = parent->children->prev; /* first child's prev is 'last child'*/
+                t = preceding->type;
+                applies_to_struct = (*(c-1) == ')') ? 1 : 0;
+                if (!applies_to_struct) {
+                  if (!(t == TPL_TYPE_BYTE   || t == TPL_TYPE_INT32 ||
+                        t == TPL_TYPE_UINT32 || t == TPL_TYPE_DOUBLE ||
+                        t == TPL_TYPE_UINT64 || t == TPL_TYPE_INT64 || 
+                        t == TPL_TYPE_UINT16 || t == TPL_TYPE_INT16 || 
+                        t == TPL_TYPE_STR )) goto fail;
+                }
+                /* count up how many contiguous # and form their product */
+                pound_prod=1;
+                num_contig_fxlens=0;
+                for(peek=c; *peek == '#'; peek++) {
+                  pound_num = va_arg(ap, int);
+                  if (pound_num < 1) {
+                    tpl_hook.fatal("non-positive iteration count %d\n", pound_num);
+                  }
+                  if (num_contig_fxlens >= (sizeof(contig_fxlens)/sizeof(contig_fxlens[0]))) {
+                    tpl_hook.fatal("contiguous # exceeds hardcoded limit\n");
+                  }
+                  contig_fxlens[num_contig_fxlens++] = pound_num;
+                  pound_prod *= pound_num;
+                }
+                /* increment c to skip contiguous # so its points to last one */
+                c = peek-1;
+                /* differentiate atom-# from struct-# by noting preceding rparen */
+                if (applies_to_struct) { /* insert # node to induce looping */
+                  n = tpl_node_new(parent);
+                  n->type = TPL_TYPE_POUND;
+                  n->num = pound_prod;
+                  n->data = tpl_hook.malloc(sizeof(tpl_pound_data));
+                  if (!n->data) fatal_oom();
+                  pd = (tpl_pound_data*)n->data;
+                  pd->inter_elt_len = inter_elt_len;
+                  pd->iter_start_node = iter_start_node; 
+                  pd->iternum = 0;
+                  DL_ADD(parent->children,n);
+                  /* multiply the 'num' and data space on each atom in the structure */
+                  for(np = iter_start_node; np != n; np = np->next) {
+                    if (n->parent->type == TPL_TYPE_ARY) {
+                      ((tpl_atyp*)(n->parent->data))->sz += 
+                         tpl_types[np->type].sz * (np->num * (n->num - 1));
+                    }
+                    np->data = tpl_hook.realloc(np->data, tpl_types[np->type].sz * 
+                                                          np->num * n->num);
+                    if (!np->data) fatal_oom();
+                    memset(np->data, 0, tpl_types[np->type].sz * np->num * n->num);
+                  }
+                } else { /* simple atom-# form does not require a loop */
+                  preceding->num = pound_prod;
+                  preceding->data = tpl_hook.realloc(preceding->data, 
+                      tpl_types[t].sz * preceding->num);
+                  if (!preceding->data) fatal_oom();
+                  memset(preceding->data,0,tpl_types[t].sz * preceding->num);
+                  if (n->parent->type == TPL_TYPE_ARY) {
+                      ((tpl_atyp*)(n->parent->data))->sz += tpl_types[t].sz * 
+                                                            (preceding->num-1);
+                  }
+                }
+                root->ser_osz += (sizeof(uint32_t) * num_contig_fxlens);
+
+                j = ((tpl_root_data*)root->data)->num_fxlens; /* before incrementing */
+                (((tpl_root_data*)root->data)->num_fxlens) += num_contig_fxlens;
+                num_fxlens = ((tpl_root_data*)root->data)->num_fxlens; /* new value */
+                fxlens = ((tpl_root_data*)root->data)->fxlens;
+                fxlens = tpl_hook.realloc(fxlens, sizeof(int) * num_fxlens);
+                if (!fxlens) fatal_oom();
+                ((tpl_root_data*)root->data)->fxlens = fxlens;
+                for(i=0; i < num_contig_fxlens; i++) fxlens[j++] = contig_fxlens[i];
+
+                break;
+            case 'B':
+                if (expect_lparen) goto fail;
+                if (in_structure) goto fail;
+                n = tpl_node_new(parent);
+                n->type = TPL_TYPE_BIN;
+                n->addr = (tpl_bin*)va_arg(ap,void*);
+                n->data = tpl_hook.malloc(sizeof(tpl_bin*));
+                if (!n->data) fatal_oom();
+                *((tpl_bin**)n->data) = NULL;
+                if (n->parent->type == TPL_TYPE_ARY) 
+                    ((tpl_atyp*)(n->parent->data))->sz += sizeof(tpl_bin);
+                DL_ADD(parent->children,n);
+                break;
+            case 'A':
+                if (in_structure) goto fail;
+                n = tpl_node_new(parent);
+                n->type = TPL_TYPE_ARY;
+                DL_ADD(parent->children,n);
+                parent = n;
+                expect_lparen=1;
+                pidx = (tpl_pidx*)tpl_hook.malloc(sizeof(tpl_pidx));
+                if (!pidx) fatal_oom();
+                pidx->node = n;
+                pidx->next = NULL;
+                DL_ADD(((tpl_root_data*)(root->data))->pidx,pidx);
+                /* set up the A's tpl_atyp */
+                n->data = (tpl_atyp*)tpl_hook.malloc(sizeof(tpl_atyp));
+                if (!n->data) fatal_oom();
+                ((tpl_atyp*)(n->data))->num = 0;
+                ((tpl_atyp*)(n->data))->sz = 0;
+                ((tpl_atyp*)(n->data))->bb = NULL;
+                ((tpl_atyp*)(n->data))->bbtail = NULL;
+                ((tpl_atyp*)(n->data))->cur = NULL;
+                if (n->parent->type == TPL_TYPE_ARY) 
+                    ((tpl_atyp*)(n->parent->data))->sz += sizeof(void*);
+                break;
+            case 'S':
+                if (in_structure) goto fail;
+                expect_lparen=1;
+                ordinal=1;  /* index upcoming atoms in S(..) */
+                in_structure=1+lparen_level; /* so we can tell where S fmt ends */
+                struct_addr = (char*)va_arg(ap,void*);
+                break;
+            case '$': /* nested structure */
+                if (!in_structure) goto fail;
+                expect_lparen=1;
+                in_nested_structure++;
+                break;
+            case ')':
+                lparen_level--;
+                if (lparen_level < 0) goto fail;
+                if (*(c-1) == '(') goto fail;
+                if (in_nested_structure) in_nested_structure--;
+                else if (in_structure && (in_structure-1 == lparen_level)) {
+                  /* calculate delta between contiguous structures in array */
+                  struct_next = calc_field_addr(parent, struct_widest_node->type, 
+                                                struct_addr, ordinal++);
+                  inter_elt_len = struct_next - struct_addr;
+                  in_structure=0;
+                }
+                else parent = parent->parent; /* rparen ends A() type, not S() type */
+                break;
+            case '(':
+                if (!expect_lparen) goto fail;
+                expect_lparen=0;
+                lparen_level++;
+                break;
+            default:
+                tpl_hook.oops("unsupported option %c\n", *c);
+                goto fail;
+        }
+        c++;
+    }
+    if (lparen_level != 0) goto fail;
+
+    /* copy the format string, save for convenience */
+    ((tpl_root_data*)(root->data))->fmt = tpl_hook.malloc(strlen(fmt)+1);
+    if (((tpl_root_data*)(root->data))->fmt == NULL) 
+        fatal_oom();
+    memcpy(((tpl_root_data*)(root->data))->fmt,fmt,strlen(fmt)+1);
+
+    return root;
+
+fail:
+    tpl_hook.oops("failed to parse %s\n", fmt);
+    tpl_free(root);
+    return NULL;
+}
+
+static int tpl_unmap_file( tpl_mmap_rec *mr) {
+
+    if ( munmap( mr->text, mr->text_sz ) == -1 ) {
+        tpl_hook.oops("Failed to munmap: %s\n", strerror(errno));
+    }
+    close(mr->fd);
+    mr->text = NULL;
+    mr->text_sz = 0;
+    return 0;
+}
+
+static void tpl_free_keep_map(tpl_node *r) {
+    int mmap_bits = (TPL_RDONLY|TPL_FILE);
+    int ufree_bits = (TPL_MEM|TPL_UFREE);
+    tpl_node *nxtc,*c;
+    int find_next_node=0,looking,i;
+    size_t sz;
+
+    /* For mmap'd files, or for 'ufree' memory images , do appropriate release */
+    if ((((tpl_root_data*)(r->data))->flags & mmap_bits) == mmap_bits) {
+        tpl_unmap_file( &((tpl_root_data*)(r->data))->mmap); 
+    } else if ((((tpl_root_data*)(r->data))->flags & ufree_bits) == ufree_bits) {
+        tpl_hook.free( ((tpl_root_data*)(r->data))->mmap.text );
+    }
+
+    c = r->children;
+    if (c) {
+        while(c->type != TPL_TYPE_ROOT) {    /* loop until we come back to root node */
+            switch (c->type) {
+                case TPL_TYPE_BIN:
+                    /* free any binary buffer hanging from tpl_bin */
+                    if ( *((tpl_bin**)(c->data)) ) {
+                        if ( (*((tpl_bin**)(c->data)))->addr ) {
+                            tpl_hook.free( (*((tpl_bin**)(c->data)))->addr );
+                        }
+                        *((tpl_bin**)c->data) = NULL; /* reset tpl_bin */
+                    }
+                    find_next_node=1;
+                    break;
+                case TPL_TYPE_STR:
+                    /* free any packed (copied) string */
+                    for(i=0; i < c->num; i++) {
+                      char *str = ((char**)c->data)[i];
+                      if (str) {
+                        tpl_hook.free(str);
+                        ((char**)c->data)[i] = NULL;
+                      }
+                    }
+                    find_next_node=1;
+                    break;
+                case TPL_TYPE_INT32:
+                case TPL_TYPE_UINT32:
+                case TPL_TYPE_INT64:
+                case TPL_TYPE_UINT64:
+                case TPL_TYPE_BYTE:
+                case TPL_TYPE_DOUBLE:
+                case TPL_TYPE_INT16:
+                case TPL_TYPE_UINT16:
+                case TPL_TYPE_POUND:
+                    find_next_node=1;
+                    break;
+                case TPL_TYPE_ARY:
+                    c->ser_osz = 0; /* zero out the serialization output size */
+
+                    sz = ((tpl_atyp*)(c->data))->sz;  /* save sz to use below */
+                    tpl_free_atyp(c,c->data);
+
+                    /* make new atyp */
+                    c->data = (tpl_atyp*)tpl_hook.malloc(sizeof(tpl_atyp));
+                    if (!c->data) fatal_oom();
+                    ((tpl_atyp*)(c->data))->num = 0;
+                    ((tpl_atyp*)(c->data))->sz = sz;  /* restore bb datum sz */
+                    ((tpl_atyp*)(c->data))->bb = NULL;
+                    ((tpl_atyp*)(c->data))->bbtail = NULL;
+                    ((tpl_atyp*)(c->data))->cur = NULL;
+
+                    c = c->children; 
+                    break;
+                default:
+                    tpl_hook.fatal("unsupported format character\n");
+                    break;
+            }
+
+            if (find_next_node) {
+                find_next_node=0;
+                looking=1;
+                while(looking) {
+                    if (c->next) {
+                        nxtc=c->next;
+                        c=nxtc;
+                        looking=0;
+                    } else {
+                        if (c->type == TPL_TYPE_ROOT) break; /* root node */
+                        else {
+                            nxtc=c->parent;
+                            c=nxtc;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    ((tpl_root_data*)(r->data))->flags = 0;  /* reset flags */
+}
+
+TPL_API void tpl_free(tpl_node *r) {
+    int mmap_bits = (TPL_RDONLY|TPL_FILE);
+    int ufree_bits = (TPL_MEM|TPL_UFREE);
+    tpl_node *nxtc,*c;
+    int find_next_node=0,looking,i;
+    tpl_pidx *pidx,*pidx_nxt;
+
+    /* For mmap'd files, or for 'ufree' memory images , do appropriate release */
+    if ((((tpl_root_data*)(r->data))->flags & mmap_bits) == mmap_bits) {
+        tpl_unmap_file( &((tpl_root_data*)(r->data))->mmap); 
+    } else if ((((tpl_root_data*)(r->data))->flags & ufree_bits) == ufree_bits) {
+        tpl_hook.free( ((tpl_root_data*)(r->data))->mmap.text );
+    }
+
+    c = r->children;
+    if (c) {
+        while(c->type != TPL_TYPE_ROOT) {    /* loop until we come back to root node */
+            switch (c->type) {
+                case TPL_TYPE_BIN:
+                    /* free any binary buffer hanging from tpl_bin */
+                    if ( *((tpl_bin**)(c->data)) ) {
+                        if ( (*((tpl_bin**)(c->data)))->sz != 0 ) {
+                            tpl_hook.free( (*((tpl_bin**)(c->data)))->addr );
+                        }
+                        tpl_hook.free(*((tpl_bin**)c->data)); /* free tpl_bin */
+                    }
+                    tpl_hook.free(c->data);  /* free tpl_bin* */
+                    find_next_node=1;
+                    break;
+                case TPL_TYPE_STR:
+                    /* free any packed (copied) string */
+                    for(i=0; i < c->num; i++) {
+                      char *str = ((char**)c->data)[i];
+                      if (str) {
+                        tpl_hook.free(str);
+                        ((char**)c->data)[i] = NULL;
+                      }
+                    }
+                    tpl_hook.free(c->data);
+                    find_next_node=1;
+                    break;
+                case TPL_TYPE_INT32:
+                case TPL_TYPE_UINT32:
+                case TPL_TYPE_INT64:
+                case TPL_TYPE_UINT64:
+                case TPL_TYPE_BYTE:
+                case TPL_TYPE_DOUBLE:
+                case TPL_TYPE_INT16:
+                case TPL_TYPE_UINT16:
+                case TPL_TYPE_POUND:
+                    tpl_hook.free(c->data);
+                    find_next_node=1;
+                    break;
+                case TPL_TYPE_ARY:
+                    tpl_free_atyp(c,c->data);
+                    if (c->children) c = c->children; /* normal case */
+                    else find_next_node=1; /* edge case, handle bad format A() */
+                    break;
+                default:
+                    tpl_hook.fatal("unsupported format character\n");
+                    break;
+            }
+
+            if (find_next_node) {
+                find_next_node=0;
+                looking=1;
+                while(looking) {
+                    if (c->next) {
+                        nxtc=c->next;
+                        tpl_hook.free(c);
+                        c=nxtc;
+                        looking=0;
+                    } else {
+                        if (c->type == TPL_TYPE_ROOT) break; /* root node */
+                        else {
+                            nxtc=c->parent;
+                            tpl_hook.free(c);
+                            c=nxtc;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /* free root */
+    for(pidx=((tpl_root_data*)(r->data))->pidx; pidx; pidx=pidx_nxt) {
+        pidx_nxt = pidx->next;
+        tpl_hook.free(pidx);
+    }
+    tpl_hook.free(((tpl_root_data*)(r->data))->fmt);
+    if (((tpl_root_data*)(r->data))->num_fxlens > 0) {
+        tpl_hook.free(((tpl_root_data*)(r->data))->fxlens);
+    }
+    tpl_hook.free(r->data);  /* tpl_root_data */
+    tpl_hook.free(r);
+}
+
+
+/* Find the i'th packable ('A' node) */
+static tpl_node *tpl_find_i(tpl_node *n, int i) {
+    int j=0;
+    tpl_pidx *pidx;
+    if (n->type != TPL_TYPE_ROOT) return NULL;
+    if (i == 0) return n;  /* packable 0 is root */
+    for(pidx=((tpl_root_data*)(n->data))->pidx; pidx; pidx=pidx->next) {
+        if (++j == i) return pidx->node;
+    }
+    return NULL;
+}
+
+static void *tpl_cpv(void *datav, void *data, size_t sz) {
+    if (sz>0) memcpy(datav,data,sz);
+    return (void*)((uintptr_t)datav + sz);
+}
+
+static void *tpl_extend_backbone(tpl_node *n) {
+    tpl_backbone *bb;
+    bb = (tpl_backbone*)tpl_hook.malloc(sizeof(tpl_backbone) +
+      ((tpl_atyp*)(n->data))->sz );  /* datum hangs on coattails of bb */
+    if (!bb) fatal_oom();
+#if __STDC_VERSION__ < 199901
+    bb->data = (char*)((uintptr_t)bb + sizeof(tpl_backbone)); 
+#endif
+    memset(bb->data,0,((tpl_atyp*)(n->data))->sz);
+    bb->next = NULL;
+    /* Add the new backbone to the tail, also setting head if necessary  */
+    if (((tpl_atyp*)(n->data))->bb == NULL) {
+        ((tpl_atyp*)(n->data))->bb = bb;
+        ((tpl_atyp*)(n->data))->bbtail = bb;
+    } else {
+        ((tpl_atyp*)(n->data))->bbtail->next = bb;
+        ((tpl_atyp*)(n->data))->bbtail = bb;
+    }
+
+    ((tpl_atyp*)(n->data))->num++;
+    return bb->data;
+}
+
+/* Get the format string corresponding to a given tpl (root node) */
+static char *tpl_fmt(tpl_node *r) {
+    return ((tpl_root_data*)(r->data))->fmt;
+}
+
+/* Get the fmt # lengths as a contiguous buffer of ints (length num_fxlens) */
+static int *tpl_fxlens(tpl_node *r, int *num_fxlens) {
+    *num_fxlens = ((tpl_root_data*)(r->data))->num_fxlens;
+    return ((tpl_root_data*)(r->data))->fxlens;
+}
+
+/* called when serializing an 'A' type node into a buffer which has
+ * already been set up with the proper space. The backbone is walked
+ * which was obtained from the tpl_atyp header passed in. 
+ */
+static void *tpl_dump_atyp(tpl_node *n, tpl_atyp* at, void *dv) {
+    tpl_backbone *bb;
+    tpl_node *c;
+    void *datav;
+    uint32_t slen;
+    tpl_bin *binp;
+    char *strp;
+    tpl_atyp *atypp;
+    tpl_pound_data *pd;
+    int i;
+    size_t itermax;
+
+    /* handle 'A' nodes */
+    dv = tpl_cpv(dv,&at->num,sizeof(uint32_t));  /* array len */
+    for(bb=at->bb; bb; bb=bb->next) {
+        datav = bb->data;
+        c=n->children;
+        while(c) {
+            switch (c->type) {
+                case TPL_TYPE_BYTE:
+                case TPL_TYPE_DOUBLE:
+                case TPL_TYPE_INT32:
+                case TPL_TYPE_UINT32:
+                case TPL_TYPE_INT64:
+                case TPL_TYPE_UINT64:
+                case TPL_TYPE_INT16:
+                case TPL_TYPE_UINT16:
+                    dv = tpl_cpv(dv,datav,tpl_types[c->type].sz * c->num);
+                    datav = (void*)((uintptr_t)datav + tpl_types[c->type].sz * c->num);
+                    break;
+                case TPL_TYPE_BIN:
+                    /* dump the buffer length followed by the buffer */
+                    memcpy(&binp,datav,sizeof(tpl_bin*)); /* cp to aligned */
+                    slen = binp->sz;
+                    dv = tpl_cpv(dv,&slen,sizeof(uint32_t));
+                    dv = tpl_cpv(dv,binp->addr,slen);
+                    datav = (void*)((uintptr_t)datav + sizeof(tpl_bin*));
+                    break;
+                case TPL_TYPE_STR:
+                    /* dump the string length followed by the string */
+                    for(i=0; i < c->num; i++) {
+                      memcpy(&strp,datav,sizeof(char*)); /* cp to aligned */
+                      slen = strp ? (strlen(strp)+1) : 0;
+                      dv = tpl_cpv(dv,&slen,sizeof(uint32_t));
+                      if (slen > 1) dv = tpl_cpv(dv,strp,slen-1);
+                      datav = (void*)((uintptr_t)datav + sizeof(char*));
+                    }
+                    break;
+                case TPL_TYPE_ARY:
+                    memcpy(&atypp,datav,sizeof(tpl_atyp*)); /* cp to aligned */
+                    dv = tpl_dump_atyp(c,atypp,dv);
+                    datav = (void*)((uintptr_t)datav + sizeof(void*));
+                    break;
+                case TPL_TYPE_POUND:
+                    /* iterate over the preceding nodes */
+                    pd = (tpl_pound_data*)c->data;
+                    itermax = c->num;
+                    if (++(pd->iternum) < itermax) {
+                      c = pd->iter_start_node;
+                      continue;
+                    } else { /* loop complete. */
+                      pd->iternum = 0;
+                    }
+                    break;
+                default:
+                    tpl_hook.fatal("unsupported format character\n");
+                    break;
+            }
+            c=c->next;
+        }
+    }
+    return dv;
+}
+
+/* figure the serialization output size needed for tpl whose root is n*/
+static size_t tpl_ser_osz(tpl_node *n) {
+    tpl_node *c, *np;
+    size_t sz, itermax;
+    tpl_bin *binp;
+    char *strp;
+    tpl_pound_data *pd;
+    int i;
+
+    /* handle the root node ONLY (subtree's ser_osz have been bubbled-up) */
+    if (n->type != TPL_TYPE_ROOT) {
+        tpl_hook.fatal("internal error: tpl_ser_osz on non-root node\n");
+    }
+
+    sz = n->ser_osz;    /* start with fixed overhead, already stored */
+    c=n->children;
+    while (c) {
+        switch (c->type) {
+            case TPL_TYPE_BYTE:
+            case TPL_TYPE_DOUBLE:
+            case TPL_TYPE_INT32:
+            case TPL_TYPE_UINT32:
+            case TPL_TYPE_INT64:
+            case TPL_TYPE_UINT64:
+            case TPL_TYPE_INT16:
+            case TPL_TYPE_UINT16:
+                sz += tpl_types[c->type].sz * c->num;
+                break;
+            case TPL_TYPE_BIN:
+                sz += sizeof(uint32_t);  /* binary buf len */
+                memcpy(&binp,c->data,sizeof(tpl_bin*)); /* cp to aligned */
+                sz += binp->sz; 
+                break;
+            case TPL_TYPE_STR:
+                for(i=0; i < c->num; i++) {
+                  sz += sizeof(uint32_t);  /* string len */
+                  memcpy(&strp,&((char**)c->data)[i],sizeof(char*)); /* cp to aligned */
+                  sz += strp ? strlen(strp) : 0;
+                }
+                break;
+            case TPL_TYPE_ARY:
+                sz += sizeof(uint32_t);  /* array len */
+                sz += c->ser_osz;        /* bubbled-up child array ser_osz */
+                break;
+            case TPL_TYPE_POUND:
+                /* iterate over the preceding nodes */
+                itermax = c->num;
+                pd = (tpl_pound_data*)c->data;
+                if (++(pd->iternum) < itermax) {
+                  for(np=pd->iter_start_node; np != c; np = np->next) {
+                     np->data = (char*)(np->data) + 
+                                (tpl_types[np->type].sz * np->num);
+                  }
+                  c = pd->iter_start_node;
+                  continue;
+                } else { /* loop complete. */
+                  pd->iternum = 0;
+                  for(np=pd->iter_start_node; np != c; np = np->next) {
+                     np->data = (char*)(np->data) - ((itermax-1) * 
+                                                     tpl_types[np->type].sz * 
+                                                     np->num);
+                  }
+                }
+                break;
+            default:
+                tpl_hook.fatal("unsupported format character\n");
+                break;
+        }
+        c=c->next;
+    }
+    return sz;
+}
+
+
+TPL_API int tpl_dump(tpl_node *r, int mode, ...) {
+    va_list ap;
+    char *filename, *bufv;
+    void **addr_out,*buf, *pa_addr;
+    int fd,rc=0;
+    size_t sz,*sz_out, pa_sz;
+
+    if (((tpl_root_data*)(r->data))->flags & TPL_RDONLY) {  /* unusual */
+        tpl_hook.oops("error: tpl_dump called for a loaded tpl\n");
+        return -1;
+    }
+
+    sz = tpl_ser_osz(r); /* compute the size needed to serialize  */
+
+    va_start(ap,mode);
+    if (mode & TPL_FILE) {
+        filename = va_arg(ap,char*);
+        fd = tpl_mmap_output_file(filename, sz, &buf);
+        if (fd == -1) rc = -1;
+        else {
+            rc = tpl_dump_to_mem(r,buf,sz);
+            if (msync(buf,sz,MS_SYNC) == -1) {
+                tpl_hook.oops("msync failed on fd %d: %s\n", fd, strerror(errno));
+            }
+            if (munmap(buf, sz) == -1) {
+                tpl_hook.oops("munmap failed on fd %d: %s\n", fd, strerror(errno));
+            }
+            close(fd);
+        }
+    } else if (mode & TPL_FD) {
+        fd = va_arg(ap, int);
+        if ( (buf = tpl_hook.malloc(sz)) == NULL) fatal_oom();
+        tpl_dump_to_mem(r,buf,sz);
+        bufv = buf;
+        do {
+            rc = write(fd,bufv,sz);
+            if (rc > 0) {
+                sz -= rc;
+                bufv += rc;
+            } else if (rc == -1) {
+                if (errno == EINTR || errno == EAGAIN) continue;
+                tpl_hook.oops("error writing to fd %d: %s\n", fd, strerror(errno));
+                free(buf);
+                return -1;
+            }
+        } while (sz > 0);
+        free(buf);
+        rc = 0;
+    } else if (mode & TPL_MEM) {
+        if (mode & TPL_PREALLOCD) { /* caller allocated */
+          pa_addr = (void*)va_arg(ap, void*);
+          pa_sz = va_arg(ap, size_t);
+          if (pa_sz < sz) {
+              tpl_hook.oops("tpl_dump: buffer too small, need %d bytes\n", sz);
+              return -1;
+          }
+          rc=tpl_dump_to_mem(r,pa_addr,sz);
+        } else { /* we allocate */
+          addr_out = (void**)va_arg(ap, void*);
+          sz_out = va_arg(ap, size_t*);
+          if ( (buf = tpl_hook.malloc(sz)) == NULL) fatal_oom();
+          *sz_out = sz;
+          *addr_out = buf;
+          rc=tpl_dump_to_mem(r,buf,sz);
+        }
+    } else if (mode & TPL_GETSIZE) {
+        sz_out = va_arg(ap, size_t*);
+        *sz_out = sz;
+    } else {
+        tpl_hook.oops("unsupported tpl_dump mode %d\n", mode);
+        rc=-1;
+    }
+    va_end(ap);
+    return rc;
+}
+
+/* This function expects the caller to have set up a memory buffer of 
+ * adequate size to hold the serialized tpl. The sz parameter must be
+ * the result of tpl_ser_osz(r).
+ */
+static int tpl_dump_to_mem(tpl_node *r,void *addr,size_t sz) {
+    uint32_t slen, sz32;
+    int *fxlens, num_fxlens, i;
+    void *dv;
+    char *fmt,flags;
+    tpl_node *c, *np;
+    tpl_pound_data *pd;
+    size_t itermax;
+
+    fmt = tpl_fmt(r);
+    flags = 0;
+    if (tpl_cpu_bigendian()) flags |= TPL_FL_BIGENDIAN;
+    if (strchr(fmt,'s')) flags |= TPL_FL_NULLSTRINGS;
+    sz32 = sz; 
+
+    dv = addr;
+    dv = tpl_cpv(dv,TPL_MAGIC,3);         /* copy tpl magic prefix */
+    dv = tpl_cpv(dv,&flags,1);            /* copy flags byte */
+    dv = tpl_cpv(dv,&sz32,sizeof(uint32_t));/* overall length (inclusive) */
+    dv = tpl_cpv(dv,fmt,strlen(fmt)+1);   /* copy format with NUL-term */
+    fxlens = tpl_fxlens(r,&num_fxlens);
+    dv = tpl_cpv(dv,fxlens,num_fxlens*sizeof(uint32_t));/* fmt # lengths */
+
+    /* serialize the tpl content, iterating over direct children of root */
+    c = r->children;
+    while (c) {
+        switch (c->type) {
+            case TPL_TYPE_BYTE:
+            case TPL_TYPE_DOUBLE:
+            case TPL_TYPE_INT32:
+            case TPL_TYPE_UINT32:
+            case TPL_TYPE_INT64:
+            case TPL_TYPE_UINT64:
+            case TPL_TYPE_INT16:
+            case TPL_TYPE_UINT16:
+                dv = tpl_cpv(dv,c->data,tpl_types[c->type].sz * c->num);
+                break;
+            case TPL_TYPE_BIN:
+                slen = (*(tpl_bin**)(c->data))->sz;
+                dv = tpl_cpv(dv,&slen,sizeof(uint32_t));  /* buffer len */
+                dv = tpl_cpv(dv,(*(tpl_bin**)(c->data))->addr,slen); /* buf */
+                break;
+            case TPL_TYPE_STR:
+                for(i=0; i < c->num; i++) {
+                  char *str = ((char**)c->data)[i];
+                  slen = str ? strlen(str)+1 : 0;
+                  dv = tpl_cpv(dv,&slen,sizeof(uint32_t));  /* string len */
+                  if (slen>1) dv = tpl_cpv(dv,str,slen-1); /*string*/
+                }
+                break;
+            case TPL_TYPE_ARY:
+                dv = tpl_dump_atyp(c,(tpl_atyp*)c->data,dv);
+                break;
+            case TPL_TYPE_POUND:
+                 pd = (tpl_pound_data*)c->data;
+                 itermax = c->num;
+                 if (++(pd->iternum) < itermax) {
+
+                   /* in start or midst of loop. advance data pointers. */
+                   for(np=pd->iter_start_node; np != c; np = np->next) {
+                     np->data = (char*)(np->data) + 
+                                (tpl_types[np->type].sz * np->num);
+                   }
+                   /* do next iteration */
+                   c = pd->iter_start_node;
+                   continue;
+
+                 } else { /* loop complete. */
+                 
+                   /* reset iteration index and addr/data pointers. */
+                   pd->iternum = 0;
+                   for(np=pd->iter_start_node; np != c; np = np->next) {
+                     np->data = (char*)(np->data) - ((itermax-1) * 
+                                                     tpl_types[np->type].sz * 
+                                                     np->num);
+                   }
+
+                 }
+                 break;
+            default:
+                tpl_hook.fatal("unsupported format character\n");
+                break;
+        }
+        c = c->next;
+    }
+
+    return 0;
+}
+
+static int tpl_cpu_bigendian() {
+   unsigned i = 1;
+   char *c;
+   c = (char*)&i;
+   return (c[0] == 1 ? 0 : 1);
+}
+
+
+/*
+ * algorithm for sanity-checking a tpl image:
+ * scan the tpl whilst not exceeding the buffer size (bufsz) ,
+ * formulating a calculated (expected) size of the tpl based
+ * on walking its data. When calcsize has been calculated it
+ * should exactly match the buffer size (bufsz) and the internal
+ * recorded size (intlsz)
+ */
+static int tpl_sanity(tpl_node *r, int excess_ok) {
+    uint32_t intlsz;
+    int found_nul=0,rc, octothorpes=0, num_fxlens, *fxlens, flen;
+    void *d, *dv;
+    char intlflags, *fmt, c, *mapfmt;
+    size_t bufsz, serlen;
+
+    d = ((tpl_root_data*)(r->data))->mmap.text;
+    bufsz = ((tpl_root_data*)(r->data))->mmap.text_sz;
+
+    dv = d;
+    if (bufsz < (4 + sizeof(uint32_t) + 1)) return ERR_NOT_MINSIZE; /* min sz: magic+flags+len+nul */
+    if (memcmp(dv,TPL_MAGIC, 3) != 0) return ERR_MAGIC_MISMATCH; /* missing tpl magic prefix */
+    if (tpl_needs_endian_swap(dv)) ((tpl_root_data*)(r->data))->flags |= TPL_XENDIAN;
+    dv = (void*)((uintptr_t)dv + 3);
+    memcpy(&intlflags,dv,sizeof(char));  /* extract flags */
+    if (intlflags & ~TPL_SUPPORTED_BITFLAGS) return ERR_UNSUPPORTED_FLAGS;
+    /* TPL1.3 stores strings with a "length+1" prefix to discern NULL strings from
+       empty strings from non-empty strings; TPL1.2 only handled the latter two. 
+       So we need to be mindful of which string format we're reading from. */
+    if (!(intlflags & TPL_FL_NULLSTRINGS)) {
+      ((tpl_root_data*)(r->data))->flags |= TPL_OLD_STRING_FMT;
+    }
+    dv = (void*)((uintptr_t)dv + 1);
+    memcpy(&intlsz,dv,sizeof(uint32_t));  /* extract internal size */
+    if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN) tpl_byteswap(&intlsz, sizeof(uint32_t));
+    if (!excess_ok && (intlsz != bufsz)) return ERR_INCONSISTENT_SZ;  /* inconsisent buffer/internal size */
+    dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+
+    /* dv points to the start of the format string. Look for nul w/in buf sz */
+    fmt = (char*)dv;
+    while ((uintptr_t)dv-(uintptr_t)d < bufsz && !found_nul) {
+        if ( (c = *(char*)dv) != '\0') {
+            if (strchr(tpl_fmt_chars,c) == NULL) 
+               return ERR_FMT_INVALID;  /* invalid char in format string */
+            if ( (c = *(char*)dv) == '#') octothorpes++;
+            dv = (void*)((uintptr_t)dv + 1);
+        }
+        else found_nul = 1;
+    }
+    if (!found_nul) return ERR_FMT_MISSING_NUL;  /* runaway format string */
+    dv = (void*)((uintptr_t)dv + 1);   /* advance to octothorpe lengths buffer */
+    
+    /* compare the map format to the format of this tpl image */
+    mapfmt = tpl_fmt(r);
+    rc = strcmp(mapfmt,fmt);
+    if (rc != 0) return ERR_FMT_MISMATCH; 
+
+    /* compare octothorpe lengths in image to the mapped values */
+    if ((((uintptr_t)dv + (octothorpes * 4)) - (uintptr_t)d) > bufsz) return ERR_INCONSISTENT_SZ4;
+    fxlens = tpl_fxlens(r,&num_fxlens);  /* mapped fxlens */
+    while(num_fxlens--) {
+        memcpy(&flen,dv,sizeof(uint32_t)); /* stored flen */
+        if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN) tpl_byteswap(&flen, sizeof(uint32_t));
+        if (flen != *fxlens) return ERR_FLEN_MISMATCH;
+        dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+        fxlens++;
+    }
+
+    /* dv now points to beginning of data */
+    rc = tpl_serlen(r,r,dv,&serlen);  /* get computed serlen of data part */
+    if (rc == -1) return ERR_INCONSISTENT_SZ2; /* internal inconsistency in tpl image */
+    serlen += ((uintptr_t)dv - (uintptr_t)d);   /* add back serlen of preamble part */
+    if (excess_ok && (bufsz < serlen)) return ERR_INCONSISTENT_SZ3;  
+    if (!excess_ok && (serlen != bufsz)) return ERR_INCONSISTENT_SZ3;  /* buffer/internal sz exceeds serlen */
+    return 0;
+}
+
+static void *tpl_find_data_start(void *d) {
+    int octothorpes=0;
+    d = (void*)((uintptr_t)d + 4); /* skip TPL_MAGIC and flags byte */
+    d = (void*)((uintptr_t)d + 4); /* skip int32 overall len */
+    while(*(char*)d != '\0') {
+        if (*(char*)d == '#') octothorpes++;
+        d = (void*)((uintptr_t)d + 1);
+    }
+    d = (void*)((uintptr_t)d +  1);  /* skip NUL */
+    d = (void*)((uintptr_t)d +  (octothorpes * sizeof(uint32_t)));  /* skip # array lens */
+    return d;
+}
+
+static int tpl_needs_endian_swap(void *d) {
+    char *c;
+    int cpu_is_bigendian;
+    c = (char*)d;
+    cpu_is_bigendian = tpl_cpu_bigendian();
+    return ((c[3] & TPL_FL_BIGENDIAN) == cpu_is_bigendian) ? 0 : 1;
+}
+
+static size_t tpl_size_for(char c) {
+  int i;
+  for(i=0; i < sizeof(tpl_types)/sizeof(tpl_types[0]); i++) {
+    if (tpl_types[i].c == c) return tpl_types[i].sz;
+  }
+  return 0;
+}
+
+TPL_API char* tpl_peek(int mode, ...) {
+    va_list ap;
+    int xendian=0,found_nul=0,old_string_format=0;
+    char *filename=NULL, *datapeek_f=NULL, *datapeek_c, *datapeek_s;
+    void *addr=NULL, *dv, *datapeek_p=NULL;
+    size_t sz=0, fmt_len, first_atom, num_fxlens=0;
+    uint32_t datapeek_ssz, datapeek_csz, datapeek_flen;
+    tpl_mmap_rec mr = {0,NULL,0};
+    char *fmt,*fmt_cpy=NULL,c;
+    uint32_t intlsz, **fxlens=NULL, *num_fxlens_out=NULL, *fxlensv;
+
+    va_start(ap,mode);
+    if ((mode & TPL_FXLENS) && (mode & TPL_DATAPEEK)) {
+        tpl_hook.oops("TPL_FXLENS and TPL_DATAPEEK mutually exclusive\n");
+        goto fail;
+    }
+    if (mode & TPL_FILE) filename = va_arg(ap,char *);
+    else if (mode & TPL_MEM) {
+        addr = va_arg(ap,void *);
+        sz = va_arg(ap,size_t);
+    } else {
+        tpl_hook.oops("unsupported tpl_peek mode %d\n", mode);
+        goto fail;
+    }
+    if (mode & TPL_DATAPEEK) {
+        datapeek_f = va_arg(ap, char*);
+    }
+    if (mode & TPL_FXLENS) {
+        num_fxlens_out = va_arg(ap,uint32_t *);
+        fxlens = va_arg(ap,uint32_t **);
+        *num_fxlens_out = 0;
+        *fxlens = NULL;
+    }
+
+    if (mode & TPL_FILE) {
+        if (tpl_mmap_file(filename, &mr) != 0) {
+            tpl_hook.oops("tpl_peek failed for file %s\n", filename);
+            goto fail;
+        }
+        addr = mr.text;
+        sz = mr.text_sz;
+    }
+
+    dv = addr;
+    if (sz < (4 + sizeof(uint32_t) + 1)) goto fail; /* min sz */
+    if (memcmp(dv,TPL_MAGIC, 3) != 0) goto fail; /* missing tpl magic prefix */
+    if (tpl_needs_endian_swap(dv)) xendian=1;
+    if ((((char*)dv)[3] & TPL_FL_NULLSTRINGS)==0) old_string_format=1;
+    dv = (void*)((uintptr_t)dv + 4);
+    memcpy(&intlsz,dv,sizeof(uint32_t));  /* extract internal size */
+    if (xendian) tpl_byteswap(&intlsz, sizeof(uint32_t));
+    if (intlsz != sz) goto fail;  /* inconsisent buffer/internal size */
+    dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+
+    /* dv points to the start of the format string. Look for nul w/in buf sz */
+    fmt = (char*)dv;
+    while ((uintptr_t)dv-(uintptr_t)addr < sz && !found_nul) {
+        if ( (c = *(char*)dv) == '\0') {
+            found_nul = 1;
+        } else if (c == '#') {
+          num_fxlens++;
+        }
+        dv = (void*)((uintptr_t)dv + 1);
+    }
+    if (!found_nul) goto fail;  /* runaway format string */
+    fmt_len = (char*)dv - fmt;  /* include space for \0 */
+    fmt_cpy = tpl_hook.malloc(fmt_len);
+    if (fmt_cpy == NULL) {
+        fatal_oom();
+    }
+    memcpy(fmt_cpy, fmt, fmt_len);
+
+    /* retrieve the octothorpic lengths if requested */
+    if (num_fxlens > 0) {
+      if (sz < ((uintptr_t)dv + (num_fxlens * sizeof(uint32_t)) - (uintptr_t)addr)) {
+        goto fail;
+      }
+    }
+    if ((mode & TPL_FXLENS) && (num_fxlens > 0)) {
+      *fxlens = tpl_hook.malloc(num_fxlens * sizeof(uint32_t));
+      if (*fxlens == NULL) tpl_hook.fatal("out of memory");
+      *num_fxlens_out = num_fxlens;
+      fxlensv = *fxlens;
+      while(num_fxlens--) {
+          memcpy(fxlensv,dv,sizeof(uint32_t)); 
+          if (xendian) tpl_byteswap(fxlensv, sizeof(uint32_t));
+          dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+          fxlensv++;
+      }
+    }
+    /* if caller requested, peek into the specified data elements */
+    if (mode & TPL_DATAPEEK) {
+
+       first_atom = strspn(fmt, "S()"); /* skip any leading S() */
+
+       datapeek_flen = strlen(datapeek_f);
+       if (strspn(datapeek_f, tpl_datapeek_ok_chars) < datapeek_flen) {
+         tpl_hook.oops("invalid TPL_DATAPEEK format: %s\n", datapeek_f);
+         tpl_hook.free(fmt_cpy); fmt_cpy = NULL; /* fail */
+         goto fail;
+       }
+
+       if (strncmp( &fmt[first_atom], datapeek_f, datapeek_flen) != 0) {
+         tpl_hook.oops("TPL_DATAPEEK format mismatches tpl iamge\n");
+         tpl_hook.free(fmt_cpy); fmt_cpy = NULL; /* fail */
+         goto fail;
+       }
+
+       /* advance to data start, then copy out requested elements */
+       dv = (void*)((uintptr_t)dv +  (num_fxlens * sizeof(uint32_t)));  
+       for(datapeek_c = datapeek_f; *datapeek_c != '\0'; datapeek_c++) {
+         datapeek_p = va_arg(ap, void*);
+         if (*datapeek_c == 's') {  /* special handling for strings */
+           if ((uintptr_t)dv-(uintptr_t)addr + sizeof(uint32_t) > sz) {
+             tpl_hook.oops("tpl_peek: tpl has insufficient length\n");
+             tpl_hook.free(fmt_cpy); fmt_cpy = NULL; /* fail */
+             goto fail;
+           }
+           memcpy(&datapeek_ssz,dv,sizeof(uint32_t)); /* get slen */
+           if (xendian) tpl_byteswap(&datapeek_ssz, sizeof(uint32_t));
+           if (old_string_format) datapeek_ssz++;
+           dv = (void*)((uintptr_t)dv + sizeof(uint32_t)); /* adv. to str */
+           if (datapeek_ssz == 0) datapeek_s = NULL;
+           else {
+             if ((uintptr_t)dv-(uintptr_t)addr + datapeek_ssz-1 > sz) {
+               tpl_hook.oops("tpl_peek: tpl has insufficient length\n");
+               tpl_hook.free(fmt_cpy); fmt_cpy = NULL; /* fail */
+               goto fail;
+             }
+             datapeek_s = tpl_hook.malloc(datapeek_ssz);
+             if (datapeek_s == NULL) fatal_oom();
+             memcpy(datapeek_s, dv, datapeek_ssz-1);
+             datapeek_s[datapeek_ssz-1] = '\0';
+             dv = (void*)((uintptr_t)dv + datapeek_ssz-1);
+           }
+           *(char**)datapeek_p = datapeek_s;
+         } else {
+           datapeek_csz = tpl_size_for(*datapeek_c);
+           if ((uintptr_t)dv-(uintptr_t)addr + datapeek_csz > sz) {
+             tpl_hook.oops("tpl_peek: tpl has insufficient length\n");
+             tpl_hook.free(fmt_cpy); fmt_cpy = NULL; /* fail */
+             goto fail;
+           }
+           memcpy(datapeek_p, dv, datapeek_csz);
+           if (xendian) tpl_byteswap(datapeek_p, datapeek_csz);
+           dv = (void*)((uintptr_t)dv + datapeek_csz);
+         }
+       }
+    }
+
+fail:
+    va_end(ap);
+    if ((mode & TPL_FILE) && mr.text != NULL) tpl_unmap_file( &mr );
+    return fmt_cpy;
+}
+
+/* tpl_jot(TPL_FILE, "file.tpl", "si", &s, &i); */
+/* tpl_jot(TPL_MEM, &buf, &sz, "si", &s, &i); */
+/* tpl_jot(TPL_FD, fd, "si", &s, &i); */
+TPL_API int tpl_jot(int mode, ...) {
+    va_list ap;
+    char *filename, *fmt;
+    size_t *sz;
+    int fd, rc=0;
+    void **buf;
+    tpl_node *tn;
+
+    va_start(ap,mode);
+    if (mode & TPL_FILE) {
+      filename = va_arg(ap,char*);
+      fmt = va_arg(ap,char*);
+      tn = tpl_map_va(fmt, ap);
+      if (tn == NULL) { rc=-1; goto fail;}
+      tpl_pack(tn, 0);
+      rc = tpl_dump(tn, TPL_FILE, filename);
+      tpl_free(tn);
+    } else if (mode & TPL_MEM) {
+      buf = va_arg(ap,void*);
+      sz = va_arg(ap,size_t*);
+      fmt = va_arg(ap,char*);
+      tn = tpl_map_va(fmt,ap);
+      if (tn == NULL) { rc=-1; goto fail;}
+      tpl_pack(tn,0);
+      rc = tpl_dump(tn, TPL_MEM, buf, sz);
+      tpl_free(tn);
+    } else if (mode & TPL_FD) {
+      fd = va_arg(ap,int);
+      fmt = va_arg(ap,char*);
+      tn = tpl_map_va(fmt,ap);
+      if (tn == NULL) { rc=-1; goto fail;}
+      tpl_pack(tn,0);
+      rc = tpl_dump(tn, TPL_FD, fd);
+      tpl_free(tn);
+    } else {
+      tpl_hook.fatal("invalid tpl_jot mode\n");
+    }
+
+fail:
+    va_end(ap);
+    return rc;
+}
+
+TPL_API int tpl_load(tpl_node *r, int mode, ...) {
+    va_list ap;
+    int rc=0,fd=0;
+    char *filename=NULL;
+    void *addr;
+    size_t sz;
+
+    va_start(ap,mode);
+    if (mode & TPL_FILE) filename = va_arg(ap,char *);
+    else if (mode & TPL_MEM) {
+        addr = va_arg(ap,void *);
+        sz = va_arg(ap,size_t);
+    } else if (mode & TPL_FD) {
+        fd = va_arg(ap,int);
+    } else {
+        tpl_hook.oops("unsupported tpl_load mode %d\n", mode);
+        return -1;
+    }
+    va_end(ap);
+
+    if (r->type != TPL_TYPE_ROOT) {
+        tpl_hook.oops("error: tpl_load to non-root node\n");
+        return -1;
+    }
+    if (((tpl_root_data*)(r->data))->flags & (TPL_WRONLY|TPL_RDONLY)) {
+        /* already packed or loaded, so reset it as if newly mapped */
+        tpl_free_keep_map(r);
+    }
+    if (mode & TPL_FILE) {
+        if (tpl_mmap_file(filename, &((tpl_root_data*)(r->data))->mmap) != 0) {
+            tpl_hook.oops("tpl_load failed for file %s\n", filename);
+            return -1;
+        }
+        if ( (rc = tpl_sanity(r, (mode & TPL_EXCESS_OK))) != 0) {
+            if (rc == ERR_FMT_MISMATCH) {
+                tpl_hook.oops("%s: format signature mismatch\n", filename);
+            } else if (rc == ERR_FLEN_MISMATCH) { 
+                tpl_hook.oops("%s: array lengths mismatch\n", filename);
+            } else { 
+                tpl_hook.oops("%s: not a valid tpl file\n", filename); 
+            }
+            tpl_unmap_file( &((tpl_root_data*)(r->data))->mmap );
+            return -1;
+        }
+        ((tpl_root_data*)(r->data))->flags = (TPL_FILE | TPL_RDONLY);
+    } else if (mode & TPL_MEM) {
+        ((tpl_root_data*)(r->data))->mmap.text = addr;
+        ((tpl_root_data*)(r->data))->mmap.text_sz = sz;
+        if ( (rc = tpl_sanity(r, (mode & TPL_EXCESS_OK))) != 0) {
+            if (rc == ERR_FMT_MISMATCH) {
+                tpl_hook.oops("format signature mismatch\n");
+            } else { 
+                tpl_hook.oops("not a valid tpl file\n"); 
+            }
+            return -1;
+        }
+        ((tpl_root_data*)(r->data))->flags = (TPL_MEM | TPL_RDONLY);
+        if (mode & TPL_UFREE) ((tpl_root_data*)(r->data))->flags |= TPL_UFREE;
+    } else if (mode & TPL_FD) {
+        /* if fd read succeeds, resulting mem img is used for load */
+        if (tpl_gather(TPL_GATHER_BLOCKING,fd,&addr,&sz) > 0) {
+            return tpl_load(r, TPL_MEM|TPL_UFREE, addr, sz);
+        } else return -1;
+    } else {
+        tpl_hook.oops("invalid tpl_load mode %d\n", mode);
+        return -1;
+    }
+    /* this applies to TPL_MEM or TPL_FILE */
+    if (tpl_needs_endian_swap(((tpl_root_data*)(r->data))->mmap.text))
+        ((tpl_root_data*)(r->data))->flags |= TPL_XENDIAN;
+    tpl_unpackA0(r);   /* prepare root A nodes for use */
+    return 0;
+}
+
+TPL_API int tpl_Alen(tpl_node *r, int i) {
+    tpl_node *n;
+
+    n = tpl_find_i(r,i);
+    if (n == NULL) {
+        tpl_hook.oops("invalid index %d to tpl_unpack\n", i);
+        return -1;
+    }
+    if (n->type != TPL_TYPE_ARY) return -1;
+    return ((tpl_atyp*)(n->data))->num;
+}
+
+static void tpl_free_atyp(tpl_node *n, tpl_atyp *atyp) {
+    tpl_backbone *bb,*bbnxt;
+    tpl_node *c;
+    void *dv;
+    tpl_bin *binp;
+    tpl_atyp *atypp;
+    char *strp;
+    size_t itermax;
+    tpl_pound_data *pd;
+    int i;
+
+    bb = atyp->bb;
+    while (bb) {
+        bbnxt = bb->next;
+        dv = bb->data;
+        c=n->children; 
+        while (c) {
+            switch (c->type) {
+                case TPL_TYPE_BYTE:
+                case TPL_TYPE_DOUBLE:
+                case TPL_TYPE_INT32:
+                case TPL_TYPE_UINT32:
+                case TPL_TYPE_INT64:
+                case TPL_TYPE_UINT64:
+                case TPL_TYPE_INT16:
+                case TPL_TYPE_UINT16:
+                    dv = (void*)((uintptr_t)dv + tpl_types[c->type].sz*c->num);
+                    break;
+                case TPL_TYPE_BIN:
+                    memcpy(&binp,dv,sizeof(tpl_bin*)); /* cp to aligned */
+                    if (binp->addr) tpl_hook.free( binp->addr ); /* free buf */
+                    tpl_hook.free(binp);  /* free tpl_bin */
+                    dv = (void*)((uintptr_t)dv + sizeof(tpl_bin*));
+                    break;
+                case TPL_TYPE_STR:
+                    for(i=0; i < c->num; i++) {
+                      memcpy(&strp,dv,sizeof(char*)); /* cp to aligned */
+                      if (strp) tpl_hook.free(strp); /* free string */
+                      dv = (void*)((uintptr_t)dv + sizeof(char*));
+                    }
+                    break;
+                case TPL_TYPE_POUND:
+                    /* iterate over the preceding nodes */
+                    itermax = c->num;
+                    pd = (tpl_pound_data*)c->data;
+                    if (++(pd->iternum) < itermax) {
+                      c = pd->iter_start_node;
+                      continue;
+                    } else { /* loop complete. */
+                      pd->iternum = 0;
+                    }
+                    break;
+                case TPL_TYPE_ARY:
+                    memcpy(&atypp,dv,sizeof(tpl_atyp*)); /* cp to aligned */
+                    tpl_free_atyp(c,atypp);  /* free atyp */
+                    dv = (void*)((uintptr_t)dv + sizeof(void*));
+                    break;
+                default:
+                    tpl_hook.fatal("unsupported format character\n");
+                    break;
+            }
+            c=c->next;
+        }
+        tpl_hook.free(bb);
+        bb = bbnxt;
+    }
+    tpl_hook.free(atyp);
+}
+
+/* determine (by walking) byte length of serialized r/A node at address dv 
+ * returns 0 on success, or -1 if the tpl isn't trustworthy (fails consistency)
+ */
+static int tpl_serlen(tpl_node *r, tpl_node *n, void *dv, size_t *serlen) {
+    uint32_t slen;
+    int num,fidx;
+    tpl_node *c;
+    size_t len=0, alen, buf_past, itermax;
+    tpl_pound_data *pd;
+
+    buf_past = ((uintptr_t)((tpl_root_data*)(r->data))->mmap.text + 
+                      ((tpl_root_data*)(r->data))->mmap.text_sz);
+
+    if (n->type == TPL_TYPE_ROOT) num = 1;
+    else if (n->type == TPL_TYPE_ARY) {
+        if ((uintptr_t)dv + sizeof(uint32_t) > buf_past) return -1;
+        memcpy(&num,dv,sizeof(uint32_t));
+        if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+             tpl_byteswap(&num, sizeof(uint32_t));
+        dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+        len += sizeof(uint32_t);
+    } else tpl_hook.fatal("internal error in tpl_serlen\n");
+
+    while (num-- > 0) {
+        c=n->children; 
+        while (c) {
+            switch (c->type) {
+                case TPL_TYPE_BYTE:
+                case TPL_TYPE_DOUBLE:
+                case TPL_TYPE_INT32:
+                case TPL_TYPE_UINT32:
+                case TPL_TYPE_INT64:
+                case TPL_TYPE_UINT64:
+                case TPL_TYPE_INT16:
+                case TPL_TYPE_UINT16:
+                    for(fidx=0; fidx < c->num; fidx++) {  /* octothorpe support */
+                        if ((uintptr_t)dv + tpl_types[c->type].sz > buf_past) return -1;
+                        dv = (void*)((uintptr_t)dv + tpl_types[c->type].sz);
+                        len += tpl_types[c->type].sz;
+                    }
+                    break;
+                case TPL_TYPE_BIN:
+                    len += sizeof(uint32_t);
+                    if ((uintptr_t)dv + sizeof(uint32_t) > buf_past) return -1;
+                    memcpy(&slen,dv,sizeof(uint32_t));
+                    if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+                        tpl_byteswap(&slen, sizeof(uint32_t));
+                    len += slen;
+                    dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+                    if ((uintptr_t)dv + slen > buf_past) return -1;
+                    dv = (void*)((uintptr_t)dv + slen);
+                    break;
+                case TPL_TYPE_STR:
+                    for(fidx=0; fidx < c->num; fidx++) {  /* octothorpe support */
+                      len += sizeof(uint32_t);
+                      if ((uintptr_t)dv + sizeof(uint32_t) > buf_past) return -1;
+                      memcpy(&slen,dv,sizeof(uint32_t));
+                      if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+                          tpl_byteswap(&slen, sizeof(uint32_t));
+                      if (!(((tpl_root_data*)(r->data))->flags & TPL_OLD_STRING_FMT))
+                         slen = (slen>1) ? (slen-1) : 0;
+                      len += slen;
+                      dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+                      if ((uintptr_t)dv + slen > buf_past) return -1;
+                      dv = (void*)((uintptr_t)dv + slen);
+                    }
+                    break;
+                case TPL_TYPE_ARY:
+                    if ( tpl_serlen(r,c,dv, &alen) == -1) return -1;
+                    dv = (void*)((uintptr_t)dv + alen);
+                    len += alen;
+                    break;
+                case TPL_TYPE_POUND:
+                    /* iterate over the preceding nodes */
+                    itermax = c->num;
+                    pd = (tpl_pound_data*)c->data;
+                    if (++(pd->iternum) < itermax) {
+                      c = pd->iter_start_node;
+                      continue;
+                    } else { /* loop complete. */
+                      pd->iternum = 0;
+                    }
+                    break;
+                default:
+                    tpl_hook.fatal("unsupported format character\n");
+                    break;
+            }
+            c=c->next;
+        }
+    }
+    *serlen = len;
+    return 0;
+}
+
+static int tpl_mmap_output_file(char *filename, size_t sz, void **text_out) {
+    void *text;
+    int fd,perms;
+
+#ifndef _WIN32
+    perms = S_IRUSR|S_IWUSR|S_IWGRP|S_IRGRP|S_IROTH;  /* ug+w o+r */
+    fd=open(filename,O_CREAT|O_TRUNC|O_RDWR,perms);
+#else
+       perms = _S_IWRITE;
+    fd=_open(filename,_O_CREAT|_O_TRUNC|_O_RDWR,perms);
+#endif
+
+    if ( fd == -1 ) {
+        tpl_hook.oops("Couldn't open file %s: %s\n", filename, strerror(errno));
+        return -1;
+    }
+
+    text = mmap(0, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    if (text == MAP_FAILED) {
+        tpl_hook.oops("Failed to mmap %s: %s\n", filename, strerror(errno));
+        close(fd);
+        return -1;
+    }
+    if (ftruncate(fd,sz) == -1) {
+        tpl_hook.oops("ftruncate failed: %s\n", strerror(errno));
+        munmap( text, sz );
+        close(fd);
+        return -1;
+    }
+    *text_out = text;
+    return fd;
+}
+
+static int tpl_mmap_file(char *filename, tpl_mmap_rec *mr) {
+    struct stat stat_buf;
+
+    if ( (mr->fd = open(filename, O_RDONLY)) == -1 ) {
+        tpl_hook.oops("Couldn't open file %s: %s\n", filename, strerror(errno));
+        return -1;
+    }
+
+    if ( fstat(mr->fd, &stat_buf) == -1) {
+        close(mr->fd);
+        tpl_hook.oops("Couldn't stat file %s: %s\n", filename, strerror(errno));
+        return -1;
+    }
+
+    mr->text_sz = (size_t)stat_buf.st_size;  
+    mr->text = mmap(0, stat_buf.st_size, PROT_READ, MAP_PRIVATE, mr->fd, 0);
+    if (mr->text == MAP_FAILED) {
+        close(mr->fd);
+        tpl_hook.oops("Failed to mmap %s: %s\n", filename, strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+TPL_API int tpl_pack(tpl_node *r, int i) {
+    tpl_node *n, *child, *np;
+    void *datav=NULL;
+    size_t sz, itermax;
+    uint32_t slen;
+    char *str;
+    tpl_bin *bin;
+    tpl_pound_data *pd;
+    int fidx;
+
+    n = tpl_find_i(r,i);
+    if (n == NULL) {
+        tpl_hook.oops("invalid index %d to tpl_pack\n", i);
+        return -1;
+    }
+
+    if (((tpl_root_data*)(r->data))->flags & TPL_RDONLY) {
+        /* convert to an writeable tpl, initially empty */
+        tpl_free_keep_map(r);
+    }
+
+    ((tpl_root_data*)(r->data))->flags |= TPL_WRONLY;
+
+    if (n->type == TPL_TYPE_ARY) datav = tpl_extend_backbone(n);
+    child = n->children;
+    while(child) {
+        switch(child->type) {
+            case TPL_TYPE_BYTE:
+            case TPL_TYPE_DOUBLE:
+            case TPL_TYPE_INT32:
+            case TPL_TYPE_UINT32:
+            case TPL_TYPE_INT64:
+            case TPL_TYPE_UINT64:
+            case TPL_TYPE_INT16:
+            case TPL_TYPE_UINT16:
+                /* no need to use fidx iteration here; we can copy multiple values in one memcpy */
+                memcpy(child->data,child->addr,tpl_types[child->type].sz * child->num);
+                if (datav) datav = tpl_cpv(datav,child->data,tpl_types[child->type].sz * child->num);
+                if (n->type == TPL_TYPE_ARY) n->ser_osz += tpl_types[child->type].sz * child->num;
+                break;
+            case TPL_TYPE_BIN:
+                /* copy the buffer to be packed */ 
+                slen = ((tpl_bin*)child->addr)->sz;
+                if (slen >0) {
+                    str = tpl_hook.malloc(slen);
+                    if (!str) fatal_oom();
+                    memcpy(str,((tpl_bin*)child->addr)->addr,slen);
+                } else str = NULL;
+                /* and make a tpl_bin to point to it */
+                bin = tpl_hook.malloc(sizeof(tpl_bin));
+                if (!bin) fatal_oom();
+                bin->addr = str;
+                bin->sz = slen;
+                /* now pack its pointer, first deep freeing any pre-existing bin */
+                if (*(tpl_bin**)(child->data) != NULL) {
+                    if ((*(tpl_bin**)(child->data))->sz != 0) {
+                            tpl_hook.free( (*(tpl_bin**)(child->data))->addr );
+                    }
+                    tpl_hook.free(*(tpl_bin**)(child->data));  
+                }
+                memcpy(child->data,&bin,sizeof(tpl_bin*));
+                if (datav) {
+                    datav = tpl_cpv(datav, &bin, sizeof(tpl_bin*));
+                    *(tpl_bin**)(child->data) = NULL;  
+                }
+                if (n->type == TPL_TYPE_ARY) {
+                    n->ser_osz += sizeof(uint32_t); /* binary buf len word */
+                    n->ser_osz += bin->sz;          /* binary buf */
+                }
+                break;
+            case TPL_TYPE_STR:
+                for(fidx=0; fidx < child->num; fidx++) {
+                  /* copy the string to be packed. slen includes \0. this 
+                     block also works if the string pointer is NULL. */
+                  char *caddr = ((char**)child->addr)[fidx];
+                  char **cdata = &((char**)child->data)[fidx];
+                  slen = caddr ?  (strlen(caddr) + 1) : 0;
+                  if (slen) {
+                    str = tpl_hook.malloc(slen);
+                    if (!str) fatal_oom();
+                    memcpy(str,caddr,slen); /* include \0 */
+                  } else {
+                    str = NULL;
+                  } 
+                  /* now pack its pointer, first freeing any pre-existing string */
+                  if (*cdata != NULL) {
+                      tpl_hook.free(*cdata);  
+                  }
+                  memcpy(cdata,&str,sizeof(char*));
+                  if (datav) {
+                      datav = tpl_cpv(datav, &str, sizeof(char*));
+                      *cdata = NULL;  
+                  }
+                  if (n->type == TPL_TYPE_ARY) {
+                      n->ser_osz += sizeof(uint32_t); /* string len word */
+                      if (slen>1) n->ser_osz += slen-1;/* string (without nul) */
+                  }
+                }
+                break;
+            case TPL_TYPE_ARY:
+                /* copy the child's tpl_atype* and reset it to empty */
+                if (datav) {
+                    sz = ((tpl_atyp*)(child->data))->sz;
+                    datav = tpl_cpv(datav, &child->data, sizeof(void*));
+                    child->data = tpl_hook.malloc(sizeof(tpl_atyp));
+                    if (!child->data) fatal_oom();
+                    ((tpl_atyp*)(child->data))->num = 0;
+                    ((tpl_atyp*)(child->data))->sz = sz;
+                    ((tpl_atyp*)(child->data))->bb = NULL;
+                    ((tpl_atyp*)(child->data))->bbtail = NULL;
+                }
+                /* parent is array? then bubble up child array's ser_osz */
+                if (n->type == TPL_TYPE_ARY) {
+                    n->ser_osz += sizeof(uint32_t); /* array len word */
+                    n->ser_osz += child->ser_osz;   /* child array ser_osz */
+                    child->ser_osz = 0;             /* reset child array ser_osz */
+                }
+                break;
+
+            case TPL_TYPE_POUND: 
+                /* we need to iterate n times over preceding nodes in S(...). 
+                 * we may be in the midst of an iteration each time or starting. */
+                 pd = (tpl_pound_data*)child->data;
+                 itermax = child->num;
+
+                 /* itermax is total num of iterations needed  */
+                 /* pd->iternum is current iteration index  */
+                 /* pd->inter_elt_len is element-to-element len of contiguous structs */
+                 /* pd->iter_start_node is where we jump to at each iteration. */
+
+                 if (++(pd->iternum) < itermax) {
+
+                   /* in start or midst of loop. advance addr/data pointers. */
+                   for(np=pd->iter_start_node; np != child; np = np->next) {
+                     np->data = (char*)(np->data) + 
+                          (tpl_types[np->type].sz * np->num);
+                     np->addr = (char*)(np->addr) + pd->inter_elt_len;
+                   }
+                   /* do next iteration */
+                   child = pd->iter_start_node;
+                   continue;
+
+                 } else { /* loop complete. */
+                 
+                   /* reset iteration index and addr/data pointers. */
+                   pd->iternum = 0;
+                   for(np=pd->iter_start_node; np != child; np = np->next) {
+                     np->data = (char*)(np->data) - ((itermax-1) *
+                                                      tpl_types[np->type].sz * 
+                                                      np->num);
+                     np->addr = (char*)(np->addr) - ((itermax-1) * pd->inter_elt_len);
+                   }
+
+                 }
+                break;
+            default:
+                tpl_hook.fatal("unsupported format character\n");
+                break;
+        }
+        child=child->next;
+    }
+    return 0;
+}
+
+TPL_API int tpl_unpack(tpl_node *r, int i) {
+    tpl_node *n, *c, *np;
+    uint32_t slen;
+    int rc=1, fidx;
+    char *str;
+    void *dv=NULL, *caddr;
+    size_t A_bytes, itermax;
+    tpl_pound_data *pd;
+    void *img;
+    size_t sz;
+
+
+    /* handle unusual case of tpl_pack,tpl_unpack without an 
+     * intervening tpl_dump. do a dump/load implicitly. */
+    if (((tpl_root_data*)(r->data))->flags & TPL_WRONLY) {
+        if (tpl_dump(r,TPL_MEM,&img,&sz) != 0) return -1;
+        if (tpl_load(r,TPL_MEM|TPL_UFREE,img,sz) != 0) {
+            tpl_hook.free(img);
+            return -1;
+        };
+    }
+
+    n = tpl_find_i(r,i);
+    if (n == NULL) {
+        tpl_hook.oops("invalid index %d to tpl_unpack\n", i);
+        return -1;
+    }
+
+    /* either root node or an A node */
+    if (n->type == TPL_TYPE_ROOT) {
+        dv = tpl_find_data_start( ((tpl_root_data*)(n->data))->mmap.text );
+    } else if (n->type == TPL_TYPE_ARY) {
+        if (((tpl_atyp*)(n->data))->num <= 0) return 0; /* array consumed */
+        else rc = ((tpl_atyp*)(n->data))->num--;
+        dv = ((tpl_atyp*)(n->data))->cur;
+        if (!dv) tpl_hook.fatal("must unpack parent of node before node itself\n");
+    }
+
+    c = n->children;
+    while (c) {
+        switch (c->type) {
+            case TPL_TYPE_BYTE:
+            case TPL_TYPE_DOUBLE:
+            case TPL_TYPE_INT32:
+            case TPL_TYPE_UINT32:
+            case TPL_TYPE_INT64:
+            case TPL_TYPE_UINT64:
+            case TPL_TYPE_INT16:
+            case TPL_TYPE_UINT16:
+                /* unpack elements of cross-endian octothorpic array individually */
+                if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN) {
+                    for(fidx=0; fidx < c->num; fidx++) {
+                        caddr = (void*)((uintptr_t)c->addr + (fidx * tpl_types[c->type].sz));
+                        memcpy(caddr,dv,tpl_types[c->type].sz);
+                        tpl_byteswap(caddr, tpl_types[c->type].sz);
+                        dv = (void*)((uintptr_t)dv + tpl_types[c->type].sz);
+                    }
+                } else {
+                    /* bulk unpack ok if not cross-endian */
+                    memcpy(c->addr, dv, tpl_types[c->type].sz * c->num);
+                    dv = (void*)((uintptr_t)dv + tpl_types[c->type].sz * c->num);
+                }
+                break;
+            case TPL_TYPE_BIN:
+                memcpy(&slen,dv,sizeof(uint32_t));
+                if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+                    tpl_byteswap(&slen, sizeof(uint32_t));
+                if (slen > 0) {
+                    str = (char*)tpl_hook.malloc(slen);
+                    if (!str) fatal_oom();
+                } else str=NULL;
+                dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+                if (slen>0) memcpy(str,dv,slen);
+                memcpy(&(((tpl_bin*)c->addr)->addr),&str,sizeof(void*));
+                memcpy(&(((tpl_bin*)c->addr)->sz),&slen,sizeof(uint32_t));
+                dv = (void*)((uintptr_t)dv + slen);
+                break;
+            case TPL_TYPE_STR:
+                for(fidx=0; fidx < c->num; fidx++) {
+                  memcpy(&slen,dv,sizeof(uint32_t));
+                  if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+                      tpl_byteswap(&slen, sizeof(uint32_t));
+                  if (((tpl_root_data*)(r->data))->flags & TPL_OLD_STRING_FMT)
+                    slen += 1;
+                  dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+                  if (slen) {  /* slen includes \0 */
+                    str = (char*)tpl_hook.malloc(slen);
+                    if (!str) fatal_oom();
+                    if (slen>1) memcpy(str,dv,slen-1);
+                    str[slen-1] = '\0'; /* nul terminate */
+                    dv = (void*)((uintptr_t)dv + slen-1);
+                  } else str=NULL;
+                  memcpy(&((char**)c->addr)[fidx],&str,sizeof(char*));
+                }
+                break;
+            case TPL_TYPE_POUND:
+                /* iterate over preceding nodes */
+                pd = (tpl_pound_data*)c->data;
+                itermax = c->num;
+                if (++(pd->iternum) < itermax) {
+                  /* in start or midst of loop. advance addr/data pointers. */
+                  for(np=pd->iter_start_node; np != c; np = np->next) {
+                    np->addr = (char*)(np->addr) + pd->inter_elt_len;
+                  }
+                  /* do next iteration */
+                  c = pd->iter_start_node;
+                  continue;
+
+                } else { /* loop complete. */
+                
+                  /* reset iteration index and addr/data pointers. */
+                  pd->iternum = 0;
+                  for(np=pd->iter_start_node; np != c; np = np->next) {
+                    np->addr = (char*)(np->addr) - ((itermax-1) * pd->inter_elt_len);
+                  }
+
+                }
+                break;
+            case TPL_TYPE_ARY:
+                if (tpl_serlen(r,c,dv, &A_bytes) == -1) 
+                    tpl_hook.fatal("internal error in unpack\n");
+                memcpy( &((tpl_atyp*)(c->data))->num, dv, sizeof(uint32_t));
+                if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+                    tpl_byteswap(&((tpl_atyp*)(c->data))->num, sizeof(uint32_t));
+                ((tpl_atyp*)(c->data))->cur = (void*)((uintptr_t)dv+sizeof(uint32_t));
+                dv = (void*)((uintptr_t)dv + A_bytes);
+                break;
+            default:
+                tpl_hook.fatal("unsupported format character\n");
+                break;
+        }
+
+        c = c->next;
+    }
+    if (n->type == TPL_TYPE_ARY) ((tpl_atyp*)(n->data))->cur = dv; /* next element */
+    return rc;
+}
+
+/* Specialized function that unpacks only the root's A nodes, after tpl_load  */
+static int tpl_unpackA0(tpl_node *r) {
+    tpl_node *n, *c;
+    uint32_t slen;
+    int rc=1,fidx,i;
+    void *dv;
+    size_t A_bytes, itermax;
+    tpl_pound_data *pd;
+
+    n = r;
+    dv = tpl_find_data_start( ((tpl_root_data*)(r->data))->mmap.text);
+
+    c=n->children;
+    while (c)  {
+        switch (c->type) {
+            case TPL_TYPE_BYTE:
+            case TPL_TYPE_DOUBLE:
+            case TPL_TYPE_INT32:
+            case TPL_TYPE_UINT32:
+            case TPL_TYPE_INT64:
+            case TPL_TYPE_UINT64:
+            case TPL_TYPE_INT16:
+            case TPL_TYPE_UINT16:
+                for(fidx=0;fidx < c->num; fidx++) {
+                    dv = (void*)((uintptr_t)dv + tpl_types[c->type].sz);
+                }
+                break;
+            case TPL_TYPE_BIN:
+                memcpy(&slen,dv,sizeof(uint32_t));
+                if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+                    tpl_byteswap(&slen, sizeof(uint32_t));
+                dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+                dv = (void*)((uintptr_t)dv + slen);
+                break;
+            case TPL_TYPE_STR:
+                for(i=0; i<c->num; i++) {
+                  memcpy(&slen,dv,sizeof(uint32_t));
+                  if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+                      tpl_byteswap(&slen, sizeof(uint32_t));
+                  if (((tpl_root_data*)(r->data))->flags & TPL_OLD_STRING_FMT)
+                    slen += 1;
+                  dv = (void*)((uintptr_t)dv + sizeof(uint32_t));
+                  if (slen>1) dv = (void*)((uintptr_t)dv + slen-1);
+                }
+                break;
+            case TPL_TYPE_POUND:
+                /* iterate over the preceding nodes */
+                itermax = c->num;
+                pd = (tpl_pound_data*)c->data;
+                if (++(pd->iternum) < itermax) {
+                  c = pd->iter_start_node;
+                  continue;
+                } else { /* loop complete. */
+                  pd->iternum = 0;
+                }
+                break;
+            case TPL_TYPE_ARY:
+                if ( tpl_serlen(r,c,dv, &A_bytes) == -1) 
+                    tpl_hook.fatal("internal error in unpackA0\n");
+                memcpy( &((tpl_atyp*)(c->data))->num, dv, sizeof(uint32_t));
+                if (((tpl_root_data*)(r->data))->flags & TPL_XENDIAN)
+                    tpl_byteswap(&((tpl_atyp*)(c->data))->num, sizeof(uint32_t));
+                ((tpl_atyp*)(c->data))->cur = (void*)((uintptr_t)dv+sizeof(uint32_t));
+                dv = (void*)((uintptr_t)dv + A_bytes);
+                break;
+            default:
+                tpl_hook.fatal("unsupported format character\n");
+                break;
+        }
+        c=c->next;
+    }
+    return rc;
+}
+
+/* In-place byte order swapping of a word of length "len" bytes */
+static void tpl_byteswap(void *word, int len) {
+    int i;
+    char c, *w;
+    w = (char*)word;
+    for(i=0; i<len/2; i++) {
+        c = w[i];
+        w[i] = w[len-1-i];
+        w[len-1-i] = c;
+    }
+}
+
+static void tpl_fatal(char *fmt, ...) {
+    va_list ap;
+    char exit_msg[100];
+
+    va_start(ap,fmt);
+    vsnprintf(exit_msg, 100, fmt, ap);
+    va_end(ap);
+
+    tpl_hook.oops("%s", exit_msg);
+    exit(-1);
+}
+
+TPL_API int tpl_gather(int mode, ...) {
+    va_list ap;
+    int fd,rc=0;
+    size_t *szp,sz;
+    void **img,*addr,*data;
+    tpl_gather_t **gs;
+    tpl_gather_cb *cb;
+
+    va_start(ap,mode);
+    switch (mode) {
+        case TPL_GATHER_BLOCKING:
+            fd = va_arg(ap,int);
+            img = va_arg(ap,void*);
+            szp = va_arg(ap,size_t*);
+            rc = tpl_gather_blocking(fd,img,szp);
+            break;
+        case TPL_GATHER_NONBLOCKING:
+            fd = va_arg(ap,int);
+            gs = (tpl_gather_t**)va_arg(ap,void*);
+            cb = (tpl_gather_cb*)va_arg(ap,tpl_gather_cb*);
+            data = va_arg(ap,void*);
+            rc = tpl_gather_nonblocking(fd,gs,cb,data);
+            break;
+        case TPL_GATHER_MEM:
+            addr = va_arg(ap,void*);
+            sz = va_arg(ap,size_t);
+            gs = (tpl_gather_t**)va_arg(ap,void*);
+            cb = (tpl_gather_cb*)va_arg(ap,tpl_gather_cb*);
+            data = va_arg(ap,void*);
+            rc = tpl_gather_mem(addr,sz,gs,cb,data);
+            break;
+        default:
+            tpl_hook.fatal("unsupported tpl_gather mode %d\n",mode);
+            break;
+    }
+    va_end(ap);
+    return rc;
+}
+
+/* dequeue a tpl by reading until one full tpl image is obtained.
+ * We take care not to read past the end of the tpl.
+ * This is intended as a blocking call i.e. for use with a blocking fd.
+ * It can be given a non-blocking fd, but the read spins if we have to wait.
+ */
+static int tpl_gather_blocking(int fd, void **img, size_t *sz) {
+    char preamble[8];
+    int i=0, rc;
+    uint32_t tpllen;
+
+    do { 
+        rc = read(fd,&preamble[i],8-i);
+        i += (rc>0) ? rc : 0;
+    } while ((rc==-1 && (errno==EINTR||errno==EAGAIN)) || (rc>0 && i<8));
+
+    if (rc<0) {
+        tpl_hook.oops("tpl_gather_fd_blocking failed: %s\n", strerror(errno));
+        return -1;
+    } else if (rc == 0) {
+        /* tpl_hook.oops("tpl_gather_fd_blocking: eof\n"); */
+        return 0;
+    } else if (i != 8) {
+        tpl_hook.oops("internal error\n");
+        return -1;
+    }
+
+    if (preamble[0] == 't' && preamble[1] == 'p' && preamble[2] == 'l') {
+        memcpy(&tpllen,&preamble[4],4);
+        if (tpl_needs_endian_swap(preamble)) tpl_byteswap(&tpllen,4);
+    } else {
+        tpl_hook.oops("tpl_gather_fd_blocking: non-tpl input\n");
+        return -1;
+    }
+
+    /* malloc space for remainder of tpl image (overall length tpllen) 
+     * and read it in
+     */
+    if (tpl_hook.gather_max > 0 && 
+        tpllen > tpl_hook.gather_max) {
+        tpl_hook.oops("tpl exceeds max length %d\n", 
+            tpl_hook.gather_max);
+        return -2;
+    }
+    *sz = tpllen;
+    if ( (*img = tpl_hook.malloc(tpllen)) == NULL) {
+        fatal_oom();
+    }
+
+    memcpy(*img,preamble,8);  /* copy preamble to output buffer */
+    i=8;
+    do { 
+        rc = read(fd,&((*(char**)img)[i]),tpllen-i);
+        i += (rc>0) ? rc : 0;
+    } while ((rc==-1 && (errno==EINTR||errno==EAGAIN)) || (rc>0 && i<tpllen));
+
+    if (rc<0) {
+        tpl_hook.oops("tpl_gather_fd_blocking failed: %s\n", strerror(errno));
+        tpl_hook.free(*img);
+        return -1;
+    } else if (rc == 0) {
+        /* tpl_hook.oops("tpl_gather_fd_blocking: eof\n"); */
+        tpl_hook.free(*img);
+        return 0;
+    } else if (i != tpllen) {
+        tpl_hook.oops("internal error\n");
+        tpl_hook.free(*img);
+        return -1;
+    }
+
+    return 1;
+}
+
+/* Used by select()-driven apps which want to gather tpl images piecemeal */
+/* the file descriptor must be non-blocking for this functino to work. */
+static int tpl_gather_nonblocking( int fd, tpl_gather_t **gs, tpl_gather_cb *cb, void *data) {
+    char buf[TPL_GATHER_BUFLEN], *img, *tpl;
+    int rc, keep_looping, cbrc=0;
+    size_t catlen;
+    uint32_t tpllen;
+
+    while (1) {
+        rc = read(fd,buf,TPL_GATHER_BUFLEN);
+        if (rc == -1) {
+            if (errno == EINTR) continue;  /* got signal during read, ignore */
+            if (errno == EAGAIN) return 1; /* nothing to read right now */
+            else {
+                tpl_hook.oops("tpl_gather failed: %s\n", strerror(errno));
+                if (*gs) {
+                    tpl_hook.free((*gs)->img);
+                    tpl_hook.free(*gs);
+                    *gs = NULL;
+                }
+                return -1;                 /* error, caller should close fd  */
+            }
+        } else if (rc == 0) {
+            if (*gs) {
+                tpl_hook.oops("tpl_gather: partial tpl image precedes EOF\n");
+                tpl_hook.free((*gs)->img);
+                tpl_hook.free(*gs);
+                *gs = NULL;
+            }
+            return 0;                      /* EOF, caller should close fd */
+        } else {
+            /* concatenate any partial tpl from last read with new buffer */
+            if (*gs) {
+                catlen = (*gs)->len + rc;
+                if (tpl_hook.gather_max > 0 && 
+                    catlen > tpl_hook.gather_max) {
+                    tpl_hook.free( (*gs)->img );
+                    tpl_hook.free( (*gs) );
+                    *gs = NULL;
+                    tpl_hook.oops("tpl exceeds max length %d\n", 
+                        tpl_hook.gather_max);
+                    return -2;              /* error, caller should close fd */
+                }
+                if ( (img = tpl_hook.realloc((*gs)->img, catlen)) == NULL) {
+                    fatal_oom();
+                }
+                memcpy(img + (*gs)->len, buf, rc);
+                tpl_hook.free(*gs);
+                *gs = NULL;
+            } else {
+                img = buf;
+                catlen = rc;
+            }
+            /* isolate any full tpl(s) in img and invoke cb for each */
+            tpl = img;
+            keep_looping = (tpl+8 < img+catlen) ? 1 : 0;
+            while (keep_looping) {
+                if (strncmp("tpl", tpl, 3) != 0) {
+                    tpl_hook.oops("tpl prefix invalid\n");
+                    if (img != buf) tpl_hook.free(img);
+                    tpl_hook.free(*gs);
+                    *gs = NULL;
+                    return -3; /* error, caller should close fd */
+                }
+                memcpy(&tpllen,&tpl[4],4);
+                if (tpl_needs_endian_swap(tpl)) tpl_byteswap(&tpllen,4);
+                if (tpl+tpllen <= img+catlen) {
+                    cbrc = (cb)(tpl,tpllen,data);  /* invoke cb for tpl image */
+                    tpl += tpllen;                 /* point to next tpl image */
+                    if (cbrc < 0) keep_looping = 0;
+                    else keep_looping = (tpl+8 < img+catlen) ? 1 : 0;
+                } else keep_looping=0;
+            } 
+            /* check if app callback requested closure of tpl source */
+            if (cbrc < 0) {
+                tpl_hook.oops("tpl_fd_gather aborted by app callback\n");
+                if (img != buf) tpl_hook.free(img);
+                if (*gs) tpl_hook.free(*gs);
+                *gs = NULL;
+                return -4;
+            }
+            /* store any leftover, partial tpl fragment for next read */
+            if (tpl == img && img != buf) {  
+                /* consumed nothing from img!=buf */
+                if ( (*gs = tpl_hook.malloc(sizeof(tpl_gather_t))) == NULL ) {
+                    fatal_oom();
+                }
+                (*gs)->img = tpl;
+                (*gs)->len = catlen;
+            } else if (tpl < img+catlen) {  
+                /* consumed 1+ tpl(s) from img!=buf or 0 from img==buf */
+                if ( (*gs = tpl_hook.malloc(sizeof(tpl_gather_t))) == NULL ) {
+                    fatal_oom();
+                }
+                if ( ((*gs)->img = tpl_hook.malloc(img+catlen - tpl)) == NULL ) {
+                    fatal_oom();
+                }
+                (*gs)->len = img+catlen - tpl;
+                memcpy( (*gs)->img, tpl, img+catlen - tpl);
+                /* free partially consumed concat buffer if used */
+                if (img != buf) tpl_hook.free(img); 
+            } else {                        /* tpl(s) fully consumed */
+                /* free consumed concat buffer if used */
+                if (img != buf) tpl_hook.free(img); 
+            }
+        }
+    } 
+}
+
+/* gather tpl piecemeal from memory buffer (not fd) e.g., from a lower-level api */
+static int tpl_gather_mem( char *buf, size_t len, tpl_gather_t **gs, tpl_gather_cb *cb, void *data) {
+    char *img, *tpl;
+    int keep_looping, cbrc=0;
+    size_t catlen;
+    uint32_t tpllen;
+
+    /* concatenate any partial tpl from last read with new buffer */
+    if (*gs) {
+        catlen = (*gs)->len + len;
+        if (tpl_hook.gather_max > 0 && 
+            catlen > tpl_hook.gather_max) {
+            tpl_hook.free( (*gs)->img );
+            tpl_hook.free( (*gs) );
+            *gs = NULL;
+            tpl_hook.oops("tpl exceeds max length %d\n", 
+                tpl_hook.gather_max);
+            return -2;              /* error, caller should stop accepting input from source*/
+        }
+        if ( (img = tpl_hook.realloc((*gs)->img, catlen)) == NULL) {
+            fatal_oom();
+        }
+        memcpy(img + (*gs)->len, buf, len);
+        tpl_hook.free(*gs);
+        *gs = NULL;
+    } else {
+        img = buf;
+        catlen = len;
+    }
+    /* isolate any full tpl(s) in img and invoke cb for each */
+    tpl = img;
+    keep_looping = (tpl+8 < img+catlen) ? 1 : 0;
+    while (keep_looping) {
+        if (strncmp("tpl", tpl, 3) != 0) {
+            tpl_hook.oops("tpl prefix invalid\n");
+            if (img != buf) tpl_hook.free(img);
+            tpl_hook.free(*gs);
+            *gs = NULL;
+            return -3; /* error, caller should stop accepting input from source*/
+        }
+        memcpy(&tpllen,&tpl[4],4);
+        if (tpl_needs_endian_swap(tpl)) tpl_byteswap(&tpllen,4);
+        if (tpl+tpllen <= img+catlen) {
+            cbrc = (cb)(tpl,tpllen,data);  /* invoke cb for tpl image */
+            tpl += tpllen;               /* point to next tpl image */
+            if (cbrc < 0) keep_looping = 0;
+            else keep_looping = (tpl+8 < img+catlen) ? 1 : 0;
+        } else keep_looping=0;
+    } 
+    /* check if app callback requested closure of tpl source */
+    if (cbrc < 0) {
+        tpl_hook.oops("tpl_mem_gather aborted by app callback\n");
+        if (img != buf) tpl_hook.free(img);
+        if (*gs) tpl_hook.free(*gs);
+        *gs = NULL;
+        return -4;
+    }
+    /* store any leftover, partial tpl fragment for next read */
+    if (tpl == img && img != buf) {  
+        /* consumed nothing from img!=buf */
+        if ( (*gs = tpl_hook.malloc(sizeof(tpl_gather_t))) == NULL ) {
+            fatal_oom();
+        }
+        (*gs)->img = tpl;
+        (*gs)->len = catlen;
+    } else if (tpl < img+catlen) {  
+        /* consumed 1+ tpl(s) from img!=buf or 0 from img==buf */
+        if ( (*gs = tpl_hook.malloc(sizeof(tpl_gather_t))) == NULL ) {
+            fatal_oom();
+        }
+        if ( ((*gs)->img = tpl_hook.malloc(img+catlen - tpl)) == NULL ) {
+            fatal_oom();
+        }
+        (*gs)->len = img+catlen - tpl;
+        memcpy( (*gs)->img, tpl, img+catlen - tpl);
+        /* free partially consumed concat buffer if used */
+        if (img != buf) tpl_hook.free(img); 
+    } else {                        /* tpl(s) fully consumed */
+        /* free consumed concat buffer if used */
+        if (img != buf) tpl_hook.free(img); 
+    }
+    return 1;
+}
diff --git a/libs/libtpl-1.5/src/tpl.h b/libs/libtpl-1.5/src/tpl.h
new file mode 100755 (executable)
index 0000000..e23953b
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+Copyright (c) 2005-2010, Troy D. Hanson     http://tpl.sourceforge.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:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+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 TPL_H
+#define TPL_H 
+
+#include <stddef.h>     /* size_t */
+
+#ifdef __INTEL_COMPILER
+#include <tbb/tbbmalloc_proxy.h>
+#endif /* Intel Compiler efficient memcpy etc */
+
+#ifdef _MSC_VER
+typedef unsigned int uint32_t;
+#else
+#include <inttypes.h>   /* uint32_t */
+#endif
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+#ifdef TPL_EXPORTS
+#define TPL_API __declspec(dllexport)
+#else                                                  /*  */
+#ifdef TPL_NOLIB
+#define TPL_API
+#else
+#define TPL_API __declspec(dllimport)
+#endif /* TPL_NOLIB */
+#endif /* TPL_EXPORTS*/
+#else
+#define TPL_API
+#endif
+
+/* bit flags (external) */
+#define TPL_FILE      (1 << 0)
+#define TPL_MEM       (1 << 1)
+#define TPL_PREALLOCD (1 << 2)
+#define TPL_EXCESS_OK (1 << 3)
+#define TPL_FD        (1 << 4)
+#define TPL_UFREE     (1 << 5)  
+#define TPL_DATAPEEK  (1 << 6)  
+#define TPL_FXLENS    (1 << 7)  
+#define TPL_GETSIZE   (1 << 8)
+/* do not add flags here without renumbering the internal flags! */
+
+/* flags for tpl_gather mode */
+#define TPL_GATHER_BLOCKING    1
+#define TPL_GATHER_NONBLOCKING 2
+#define TPL_GATHER_MEM         3
+
+/* Hooks for error logging, memory allocation functions and fatal */
+typedef int (tpl_print_fcn)(const char *fmt, ...);
+typedef void *(tpl_malloc_fcn)(size_t sz);
+typedef void *(tpl_realloc_fcn)(void *ptr, size_t sz);
+typedef void (tpl_free_fcn)(void *ptr);
+typedef void (tpl_fatal_fcn)(char *fmt, ...);
+
+typedef struct tpl_hook_t {
+    tpl_print_fcn *oops;
+    tpl_malloc_fcn *malloc;
+    tpl_realloc_fcn *realloc;
+    tpl_free_fcn *free;
+    tpl_fatal_fcn *fatal;
+    size_t gather_max;
+} tpl_hook_t;
+
+typedef struct tpl_node {
+    int type;
+    void *addr;
+    void *data;                  /* r:tpl_root_data*. A:tpl_atyp*. ow:szof type */
+    int num;                     /* length of type if its a C array */
+    size_t ser_osz;              /* serialization output size for subtree */
+    struct tpl_node *children;   /* my children; linked-list */
+    struct tpl_node *next,*prev; /* my siblings (next child of my parent) */
+    struct tpl_node *parent;     /* my parent */
+} tpl_node;
+
+/* used when un/packing 'B' type (binary buffers) */
+typedef struct tpl_bin {
+    void *addr;
+    uint32_t sz;
+} tpl_bin;
+
+/* for async/piecemeal reading of tpl images */
+typedef struct tpl_gather_t {
+    char *img;
+    int len;
+} tpl_gather_t;
+
+/* Callback used when tpl_gather has read a full tpl image */
+typedef int (tpl_gather_cb)(void *img, size_t sz, void *data);
+
+/* Prototypes */
+TPL_API tpl_node *tpl_map(char *fmt,...);       /* define tpl using format */
+TPL_API void tpl_free(tpl_node *r);             /* free a tpl map */
+TPL_API int tpl_pack(tpl_node *r, int i);       /* pack the n'th packable */
+TPL_API int tpl_unpack(tpl_node *r, int i);     /* unpack the n'th packable */
+TPL_API int tpl_dump(tpl_node *r, int mode, ...); /* serialize to mem/file */
+TPL_API int tpl_load(tpl_node *r, int mode, ...); /* set mem/file to unpack */
+TPL_API int tpl_Alen(tpl_node *r, int i);      /* array len of packable i */
+TPL_API char* tpl_peek(int mode, ...);         /* sneak peek at format string */
+TPL_API int tpl_gather( int mode, ...);        /* non-blocking image gather */
+TPL_API int tpl_jot(int mode, ...);            /* quick write a simple tpl */
+
+#if defined __cplusplus
+    }
+#endif
+
+#endif /* TPL_H */
+
diff --git a/libs/libtpl-1.5/src/win/Makefile.am b/libs/libtpl-1.5/src/win/Makefile.am
new file mode 100755 (executable)
index 0000000..8282237
--- /dev/null
@@ -0,0 +1,4 @@
+noinst_LTLIBRARIES = libwinmmap.la
+noinst_HEADERS = mman.h
+libwinmmap_la_SOURCES = nonempty.c
+libwinmmap_la_LIBADD = @LTLIBOBJS@
diff --git a/libs/libtpl-1.5/src/win/Makefile.in b/libs/libtpl-1.5/src/win/Makefile.in
new file mode 100644 (file)
index 0000000..9ff433e
--- /dev/null
@@ -0,0 +1,440 @@
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008  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.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/win
+DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in mmap.c
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libwinmmap_la_DEPENDENCIES = @LTLIBOBJS@
+am_libwinmmap_la_OBJECTS = nonempty.lo
+libwinmmap_la_OBJECTS = $(am_libwinmmap_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+       --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+       $(LDFLAGS) -o $@
+SOURCES = $(libwinmmap_la_SOURCES)
+DIST_SOURCES = $(libwinmmap_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = libwinmmap.la
+noinst_HEADERS = mman.h
+libwinmmap_la_SOURCES = nonempty.c
+libwinmmap_la_LIBADD = @LTLIBOBJS@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/win/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  src/win/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+       @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+libwinmmap.la: $(libwinmmap_la_OBJECTS) $(libwinmmap_la_DEPENDENCIES) 
+       $(LINK)  $(libwinmmap_la_OBJECTS) $(libwinmmap_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mmap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonempty.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf $(DEPDIR) ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf $(DEPDIR) ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+       distclean-compile distclean-generic distclean-libtool \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+# 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/libs/libtpl-1.5/src/win/README b/libs/libtpl-1.5/src/win/README
new file mode 100755 (executable)
index 0000000..4d055c1
--- /dev/null
@@ -0,0 +1,11 @@
+This directory contains functions that are missing on the Windows platform.  In
+particular, mmap, munmap, and msync are not available on Windows. These
+replacements are used on both Cygwin and MinGW. (On Cygwin the built-in mmap
+has no write support, and is not used).
+
+mmap.c
+mman.h
+
+Special thanks to Horea Haitonic for contributing mmap.c and mman.h.
+
+April 2007
diff --git a/libs/libtpl-1.5/src/win/mman.h b/libs/libtpl-1.5/src/win/mman.h
new file mode 100755 (executable)
index 0000000..9f97ac0
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef _MMAN_H_
+#define _MMAN_H_
+
+/* Protections */
+#define PROT_NONE       0x00    /* no permissions */
+#define PROT_READ       0x01    /* pages can be read */
+#define PROT_WRITE      0x02    /* pages can be written */
+#define PROT_EXEC       0x04    /* pages can be executed */
+
+/* Sharing type and options */
+#define MAP_SHARED      0x0001          /* share changes */
+#define MAP_PRIVATE     0x0002          /* changes are private */
+#define MAP_COPY        MAP_PRIVATE     /* Obsolete */
+#define MAP_FIXED        0x0010 /* map addr must be exactly as requested */
+#define MAP_RENAME       0x0020 /* Sun: rename private pages to file */
+#define MAP_NORESERVE    0x0040 /* Sun: don't reserve needed swap area */
+#define MAP_INHERIT      0x0080 /* region is retained after exec */
+#define MAP_NOEXTEND     0x0100 /* for MAP_FILE, don't change file size */
+#define MAP_HASSEMAPHORE 0x0200 /* region may contain semaphores */
+#define MAP_STACK        0x0400 /* region grows down, like a stack */
+
+/* Error returned from mmap() */
+#define MAP_FAILED      ((void *)-1)
+
+/* Flags to msync */
+#define MS_ASYNC        0x01    /* perform asynchronous writes */
+#define MS_SYNC         0x02    /* perform synchronous writes */
+#define MS_INVALIDATE   0x04    /* invalidate cached data */
+
+/* File modes for 'open' not defined in MinGW32  (not used by mmap) */
+#ifndef S_IWGRP
+#define S_IWGRP 0
+#define S_IRGRP 0
+#define S_IROTH 0
+#endif
+
+/**
+ * Map a file to a memory region
+ */
+void *mmap(void *addr, unsigned int len, int prot, int flags, int fd, unsigned int offset);
+
+/**
+ * Unmap a memory region
+ */
+int munmap(void *addr, int len);
+
+/**
+ * Synchronize a mapped region
+ */
+int msync(char *addr, int len, int flags);
+
+#endif /* _MMAN_H_ */
diff --git a/libs/libtpl-1.5/src/win/mmap.c b/libs/libtpl-1.5/src/win/mmap.c
new file mode 100755 (executable)
index 0000000..b06cd35
--- /dev/null
@@ -0,0 +1,170 @@
+#include <stdlib.h>
+#include <windows.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+#include <errno.h>
+#include "mman.h"
+
+static const char id[]="$Id: tpl.c 107 2007-04-20 17:11:29Z thanson $";
+
+/**
+ * @brief Map a file to a memory region
+ *
+ * This function emulates the POSIX mmap() using CreateFileMapping() and
+ * MapViewOfFile()
+ *
+ * @param addr the suggested start address (if != 0)
+ * @param len length of the region
+ * @param prot region accesibility, bitwise OR of PROT_READ, PROT_WRITE, PROT_EXEC
+ * @param flags mapping type and options (ignored)
+ * @param fd object to be mapped into memory
+ * @param offset offset into mapped object
+ * @return pointer to the memory region, or NULL in case of error
+ */
+void *mmap(void *addr, unsigned int len, int prot, int flags, int fd, unsigned int offset)
+{
+       DWORD wprot;
+       DWORD waccess;
+       HANDLE h;
+       void *region;
+
+       /* Translate read/write/exec flags into WIN32 constants */
+       switch (prot) {
+       case PROT_READ:
+               wprot = PAGE_READONLY;
+               break;
+       case PROT_EXEC:
+               wprot = PAGE_EXECUTE_READ;
+               break;
+       case PROT_READ | PROT_EXEC:
+               wprot = PAGE_EXECUTE_READ;
+               break;
+       case PROT_WRITE:
+               wprot = PAGE_READWRITE;
+               break;
+       case PROT_READ | PROT_WRITE:
+               wprot = PAGE_READWRITE;
+               break;
+       case PROT_READ | PROT_WRITE | PROT_EXEC:
+               wprot = PAGE_EXECUTE_READWRITE;
+               break;
+       case PROT_WRITE | PROT_EXEC:
+               wprot = PAGE_EXECUTE_READWRITE;
+               break;
+       }
+       
+       /* Obtaing handle to map region */
+       h = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, wprot, 0, len, 0);
+       if (h == NULL) {
+               DWORD error = GetLastError();
+
+               /* Try and translate some error codes */
+               switch (error) {
+               case ERROR_ACCESS_DENIED:
+               case ERROR_INVALID_ACCESS:
+                       errno = EACCES;
+                       break;
+               case ERROR_OUTOFMEMORY:
+               case ERROR_NOT_ENOUGH_MEMORY:
+                       errno = ENOMEM;
+                       break;
+               default:
+                       errno = EINVAL;
+                       break;
+               }
+               return MAP_FAILED;
+       }
+                       
+
+       /* Translate sharing options into WIN32 constants */
+       switch (wprot) {
+       case PAGE_READONLY:
+               waccess = FILE_MAP_READ;
+               break;
+       case PAGE_READWRITE:
+               waccess = FILE_MAP_WRITE;
+               break;
+       }
+
+       /* Map file and return pointer */
+       region = MapViewOfFile(h, waccess, 0, 0, 0);
+       if (region == NULL) {
+               DWORD error = GetLastError();
+
+               /* Try and translate some error codes */
+               switch (error) {
+               case ERROR_ACCESS_DENIED:
+               case ERROR_INVALID_ACCESS:
+                       errno = EACCES;
+                       break;
+               case ERROR_INVALID_HANDLE:
+                       errno = EBADF;
+                       break;
+               default:
+                       errno = EINVAL;
+                       break;
+               }
+               CloseHandle(h);
+               return MAP_FAILED;
+       }
+       
+       /* All fine */
+       return region;
+}
+
+
+/**
+ * @brief Unmap a memory region
+ *
+ * This is a wrapper around UnmapViewOfFile in the win32 API
+ * 
+ * @param addr start address
+ * @param len length of the region
+ * @return 0 for success, -1 for error
+ */
+int munmap(void *addr, int len) 
+{
+       if (UnmapViewOfFile(addr)) {
+               return 0;
+       }
+       else {
+               errno = EINVAL;
+               return -1;
+       }
+}
+
+
+/**
+ * Synchronize a mapped region
+ *
+ * This is a wrapper around FlushViewOfFile
+ *
+ * @param addr start address
+ * @param len number of bytes to flush
+ * @param flags sync options -- currently ignored
+ * @return 0 for success, -1 for error
+ */
+int msync(char *addr, int len, int flags) 
+{
+       if (FlushViewOfFile(addr, len) == 0) {
+               DWORD error = GetLastError();
+               
+               /* Try and translate some error codes */
+               switch (error) {
+               case ERROR_INVALID_PARAMETER:
+                       errno = EINVAL;
+                       break;
+               case ERROR_WRITE_FAULT:
+                       errno = EIO;
+                       break;
+               default:
+                       errno = EINVAL;
+                       break;
+               }
+               return -1;
+       }
+
+       /* Success */
+       return 0;
+}
diff --git a/libs/libtpl-1.5/src/win/nonempty.c b/libs/libtpl-1.5/src/win/nonempty.c
new file mode 100755 (executable)
index 0000000..5c02f16
--- /dev/null
@@ -0,0 +1,6 @@
+/* This function exists solely to prevent libwinmmap.la from being empty. Empty
+ * libraries cause problems on some platforms, e.g. Mac OS X. */
+
+int tpl_nonempty(int i) {
+    return i+1;
+}
diff --git a/libs/libtpl-1.5/tests/Makefile b/libs/libtpl-1.5/tests/Makefile
new file mode 100755 (executable)
index 0000000..6ebd127
--- /dev/null
@@ -0,0 +1,88 @@
+# Makefile for tpl built-in test suite
+# 
+# This Makefile has three useful targets:
+#
+# all (default): 
+#    Build and run all self-tests by compiling tpl into each test. 
+#
+#    Note: On Cygwin/MinGW, compiling the tpl source directly into the tests is
+#    not supported (as they use 'replacement' functions which get included only
+#    in libtpl), so on these platforms the 'alt' target is the default.
+#
+# alt:
+#    Build and run all the self-tests by linking them with libtpl, which must
+#    have been created beforehand (by running 'configure; make' in the
+#    top-level directory); a reminder will be printed if you have not done so.
+#
+#    Note, libtool will create wrappers around each test to accomodate the 
+#    pre-installed state of ../src/libtpl.la. In a real program, you'd link 
+#    against an installed libtpl.la, and these wrappers would not be used.
+#
+# clean:
+#    Clean up all the compiled bits.
+#
+PROGS = test1 test2 test3 test4 test5 test6 test7 test8 \
+       test9 test10 test11 test12 test13 test14 test15 test16 \
+       test17 test18 test19 test20 test21 test22 test23 test24 \
+       test25 test26 test27 test28 test29 test30 test31 test32 \
+       test33 test34 test35 test36 test37 test38 test39 test40 \
+       test41 test42 test43 test44 test45 test46 test47 test48 \
+       test49 test50 test51 test52 test53 test54 test55 test56 \
+       test57 test58 test59 test60 test61 test62 test63 test64 \
+    test65 test66 test67 test68 test69 test70 test71 test72 \
+    test73 test74 test75 test76 test77 test78 test79 test80 \
+    test81 test82 test83 test84 test85 test86 test87 test88 \
+    test89 test90 test91 test92 test93 test94 test95 test96 \
+    test97 test98 test99 test100 test101 test102 test103 test104 \
+    test105 test106 test107 test108 test109 test110 test111 test112 \
+    test113 test114 test115 test116 test117 test118 test119 test120 \
+    test121 test122 test123 test124
+
+TPLSRC = ../src
+CFLAGS = -I$(TPLSRC) -g
+CFLAGS += -pedantic 
+CFLAGS += -Wall 
+#CFLAGS += -m32
+#CFLAGS += -m64
+CFLAGS += -O3
+#For testing without C99 feature support
+#CFLAGS += -std=c89
+
+# Prefer 64-bit compilation on Mac OS X (not necessary, just faster)
+ifneq ($(strip $(shell $(CC) -v 2>&1 |egrep "i[0-9]+-apple-darwin")),)
+  CFLAGS += -m64
+endif
+
+# detect Cygwin or MinGW
+ifneq ($(strip $(shell $(CC) -v 2>&1 |egrep "cygwin|mingw")),)
+  TESTS=./do_tests.cygwin
+  # divert to the alt target; use tpl as a lib for Cygwin/Mingw 
+  TARGET=alt
+else
+  TESTS=./do_tests
+  TARGET=$(PROGS) run_tests
+endif
+
+all: $(TARGET) 
+
+tpl.o :        $(TPLSRC)/tpl.c $(TPLSRC)/tpl.h
+       $(CC) -c $(CFLAGS) $(TPLSRC)/tpl.c
+
+$(PROGS) : tpl.o 
+       $(CC) $(CFLAGS) -o $@ $(@).c tpl.o
+
+run_tests: 
+       perl $(TESTS)
+
+# This target can be used to compile the tests as dependent on
+# the tpl library (rather than compiling in the tpl source).
+alt: mkalttests run_tests
+
+mkalttests:
+       @$(MAKE) -f Makefile.alt PROGS="$(PROGS)" 
+
+.PHONY: clean 
+
+clean: 
+       rm -f $(PROGS) tpl.o test*.out test*.err test*.exe 
+       rm -rf $(PROGS) test*.dSYM
diff --git a/libs/libtpl-1.5/tests/Makefile.alt b/libs/libtpl-1.5/tests/Makefile.alt
new file mode 100755 (executable)
index 0000000..054b678
--- /dev/null
@@ -0,0 +1,31 @@
+# This Makefile.alt is subordinate to Makefile (usage: make alt)
+# Its distinction is that it builds the test programs by linking
+# them with libtpl rather than by compiling tpl.c into the tests.
+SRC = ../src
+LIBTOOL = ../libtool
+LTLIB = $(SRC)/libtpl.la
+CFLAGS = -I$(SRC) -g 
+
+# We have an alternate basic test for MinGW
+ifneq ($(strip $(shell $(CC) -v 2>&1 |grep "mingw")),)
+  TARGET=mingw
+else
+  TARGET=$(PROGS)
+endif
+
+all: $(TARGET)
+
+
+$(PROGS) : $(LTLIB)
+       $(CC) -c $(CFLAGS) $(@).c 
+       $(LIBTOOL) --mode=link --tag=CC $(CC) -o $@ $(@).o $(LTLIB)
+
+$(LTLIB) :
+       @echo "you must first run 'configure; make' in the top-level directory"
+       @exit 1
+
+mingw :
+       @echo ""
+       @echo "MinGW has its own test suite. Please run make -f Makefile.mingw"
+       @echo ""
+       @exit 1
diff --git a/libs/libtpl-1.5/tests/Makefile.mingw b/libs/libtpl-1.5/tests/Makefile.mingw
new file mode 100755 (executable)
index 0000000..dbf7906
--- /dev/null
@@ -0,0 +1,25 @@
+# This makes a small Mingw test program. The standard test suite
+# is incompatible with MinGW because it uses UNIX facilities such
+# as pipe/fork and the /tmp directory, not features of Windows.
+SRC = ../src
+LIBTOOL = ../libtool
+LTLIB = $(SRC)/libtpl.la
+CFLAGS = -I$(SRC) -g 
+
+PROG = mgwtest
+
+all: $(PROG)
+
+$(PROG) : $(LTLIB)
+       $(CC) -c $(CFLAGS) $(@).c 
+       $(LIBTOOL) --mode=link --tag=CC $(CC) -o $@ $(@).o $(LTLIB) -mwindows
+       @echo "you can now run windows application: $@"
+
+$(LTLIB) :
+       @echo "you must first run 'configure; make' in the top-level directory"
+       @exit 1
+
+.PHONY: clean
+
+clean:
+       rm $(PROG) $(PROG).exe $(PROG).o $(PROG).tpl
diff --git a/libs/libtpl-1.5/tests/README b/libs/libtpl-1.5/tests/README
new file mode 100755 (executable)
index 0000000..eef1f17
--- /dev/null
@@ -0,0 +1,125 @@
+Run "make" in this directory to build the tests and run them.
+
+test1: serialize int into memory, unserialize 
+test2: serialize int into file, unserialize 
+test3: serialize A(i) into file, unserialize 
+test4: serialize A(i) into memory, unserialize 
+test5: serialize A(A(i)) into memory, unserialize 
+test6: serialize string into memory, unserialize 
+test7: serialize A(s) into file, unserialize 
+test8: serialize cA(c) into file, unserialize 
+test9: unpack big-endian tpl data file of A(i) 
+test10: unpack little-endian tpl data file of A(i) 
+test11: try to load a corrupt tpl image w/invalid chars
+test12: try to load a corrupt tpl image w/runaway format string
+test13: try to load a corrupt tpl image w/internal A length -1
+test14: try to load a corrupt tpl image w/internal A length +1
+test15: try to load a corrupt tpl image w/invalid magic
+test16: try to load a corrupt tpl image w/invalid len 
+test17: try to load a good tpl but whose format mismatches map
+test18: try to map a tpl with malformed format- unbalanced parens: missing )
+test19: try to map a tpl with malformed format- unbalanced parens: extra )
+test20: try to map a tpl with malformed format- empty A() 
+test21: serialize A(ii) into file, unserialize
+test22: serialize A(u) into file, unserialize
+test23: serialize A(u) into file, read tpl from fd using TPL_FD 
+test24: read A(u) tpl file with extra trailing bytes, ok in TPL_FD mode 
+test25: same A(u) tpl file with extra trailing bytes, not ok in TPL_FILE mode 
+test26: test non-blocking tpl_gather using async read of 3 tpls across 2 pipes
+test27: test tpl_dump() of A(u) to file using TPL_FD, unserialize
+test28: parent writes A(u) tpl to child through pipe, both use TPL_FD mode
+test29: parent writes consecutive A(u) tpl then A(c) tpl to child through pipe
+test30: test pack B (binary buffer) and unpack
+test31: test pack B (binary buffer) of 0-length and unpack
+test32: test pack A(B) and unpack
+test33: test pack f (double) and unpack
+test34: test pack A(f) and unpack
+test35: pack A(is) 
+test36: unpack A(is) 
+test37: pack A(A(i)) [example from man page]
+test38: unpack A(A(i)) [example from man page]
+test39: try to load a tpl with an unsupported bit flag set
+test40: pack char array - userguide example
+test41: unpack char arrray - userguide example
+test42: test non-aligned pointers in backbone (under Solaris dbx, check -all)
+test43: test non-aligned pointers in backbone (under Solaris dbx, check -all)
+test44: test non-aligned pointers in backbone (under Solaris dbx, check -all)
+test46: test correct-size of backbone "double" datum (Solaris dbx, check -all)
+test47: store A(i) to file - userguide example
+test48: read A(i) from file - userguide example
+test49: write A(s) - userguide example
+test50: read A(s) - userguide example
+test51: test tpl_mem_gather (_0: 1 tpl; _1: 2 tpls; _2/_3/_4: 1 tpl in 3 parts) 
+test52: A(A(i)): pack an int; pack parent; pack int; don't pack parent; ser_osz
+test53: A(A(i)): pack an int; pack parent; pack parent; 0-length 2nd parent el.
+test54: test callback negative return value for tpl_mem_gather
+test55: test callback negative return value for tpl_fd_gather
+test56: test static string using c# format pack/unpack in mem
+test57: test pack static string using c# to file
+test58: test unpack static string using c# from file
+test59: test alignment using cc#cc# pack/unpack in mem
+test60: test pack-then-load (implicit intervening free, using tpl_free_keep_map)
+test61: test load-then-load (implicit intervening free, using tpl_free_keep_map)
+test62: test load-then-pack (implicit intervening free, using tpl_free_keep_map)
+test63: test pack-then-unpack (implicit dump/load) then pack-then-unpack again  
+test64: pack level 0 types, change and re-pack level 0 types, test implicit free
+test65: pack int[] using format character #
+test66: pack two separate int[] using format character #
+test67: test expected failure if format strings agree but array lengths mismatch
+test68: test octothorpe support by packing,unpacking two fixed lengths arrays 
+test69: test octothorpic array support A(i#i#)
+test70: test S(...) structure pack and unpack
+test71: test cS(...) pack/unpack when preceded by non-structure byte
+test72: test wildcard structure unpack 
+test73: test wildcard structure unpack 
+test74: test wildcard structure unpack 
+test75: test sc# (string and byte array)
+test76: test S(sc#) (structure of last)
+test77: test S(sc#) (structure of last) with wildcard unpack
+test78: pack A(i)c 
+test79: unpack A(i)c 
+test80: pack and unpack A(S(ci#))
+test81: pack and unpack A(S(ci#))
+test82: pack cA(i#)S(cf#)A(ci#)
+test83: unpack cA(i#)S(cf#)A(ci#)
+test84: repeat test83 with both big and little endian input files
+test85: tpl_peek at file
+test86: tpl_peek at in-memory tpl
+test87: test tpl_gather(TPL_GATHER_FD_BLOCKING)
+test88: test packing S(ic#f)
+test89: test unpacking S(ic#f) as S(*)
+test90: pack and unpack I
+test91: pack and unpack U
+test92: pack and unpack A(cIcU)
+test93: pack and unpack NULL string
+test94: pack and unpack A(s) with some null
+test95: pack and unpack null string, empty string, non-empty string
+test96: pack and unpack A(null string, empty string, non-empty string)
+test97: pack and unapck 16-bit int/uint (j,v)
+test98: pack and unapck 16-bit int/uint A(j,v)
+test99: data peek at c in complex format
+test100: data peek at i inside S(ic)
+test101: data peek at c inside S(ic) [expected failure test]
+test102: data peek at c in simple format c
+test103: data peek at iscsi in S(iscsiu)
+test104: data peek at iscsi in S(iscsiu) with NULL string pointer
+test105: tpl_jot then unpack by normal then by tpl_peek
+test106: test IS(Iiuijc#)#iiii 
+test107: test S(ic#)#
+test108: test IS(Iiuijc#)#iiii 
+test109: test S(cijc)# where next structure elt alignment based on i
+test110: test ssssiiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiii
+test111: test S(icfv#)#
+test112: test S(ic#fv#)#
+test113: test icS(ic#fv#)#ci
+test114: test multi-dimension i##
+test115: test S(s)#, S(si)#, S(c#si)#
+test116: test cs#i
+test117: test cA(s#)i
+test118: test tpl_peek(TPL_FXLENS) with cA(i#)S(cf#)A(ci#)
+test119: test tpl_dump(tn,TPL_GETSIZE,&sz);
+test120: test TPL_PREALLOCD and TPL_EXCESS_OK flags
+test121: test s##
+test122: test S(ic#f$(ci))
+test123: setjmp/longjmp based fatal error handler
+test124: test A(S(c#)s) as per bug report from Eric Rose
diff --git a/libs/libtpl-1.5/tests/dbx.sh b/libs/libtpl-1.5/tests/dbx.sh
new file mode 100755 (executable)
index 0000000..c9fd876
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# This script works with Solaris Studio 11
+# version of dbx which supports "check -all" and
+# "check -access" run modes, at least on Sparc.
+# These detect access or alignment violations or
+# leftover unfreed memory.           TDH 29Dec06
+
+DBX=/opt/SUNWspro/bin/dbx
+OUT=/tmp/dbx.out.$$
+
+echo "Writing $OUT..."
+
+for f in test? test??
+do
+    echo $f
+    ${DBX} $f 1>>${OUT} 2>&1 <<EOF
+check -all
+run
+EOF
+
+egrep 'mar|rua|rui|wui|wua|maw' ${OUT}
+
+done
diff --git a/libs/libtpl-1.5/tests/do_tests b/libs/libtpl-1.5/tests/do_tests
new file mode 100755 (executable)
index 0000000..e6809a1
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my @tests;
+for (glob "test*[0-9]") {
+    push @tests, $_ if -e "$_.ans";
+}
+
+my $num_failed=0;
+
+for my $test (@tests) {
+    `./$test > $test.out 2> $test.err`;
+    `diff $test.out $test.ans`;
+    print "$test failed\n" if $?;
+    $num_failed++ if $?;
+    unlink "$test.err" if -z "$test.err";
+}
+
+print scalar @tests . " tests conducted, $num_failed failed.\n";
+exit $num_failed;
diff --git a/libs/libtpl-1.5/tests/do_tests.cygwin b/libs/libtpl-1.5/tests/do_tests.cygwin
new file mode 100755 (executable)
index 0000000..a9b72e0
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my @tests;
+for (glob "test*[0-9].exe") {
+    push @tests, "$_" if -e substr($_, 0, - 4).".ans";
+}
+
+my $num_failed=0;
+
+for my $test (@tests) {
+    `./$test > $test.out`;
+    my $ansfile = substr($test, 0, - 4).".ans";
+    `diff $test.out $ansfile`;
+    print "$test failed\n" if $?;
+    $num_failed++ if $?;
+}
+
+print scalar @tests . " tests conducted, $num_failed failed.\n";
diff --git a/libs/libtpl-1.5/tests/int64_align.c b/libs/libtpl-1.5/tests/int64_align.c
new file mode 100755 (executable)
index 0000000..a1a7bfc
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <inttypes.h>
+
+/* try compiling this with -m32 vs -m64
+ * 
+ * with mac os x and gcc, 
+ * on -m32 the int64_t gets aligned at +4
+ * on -m64 the int64_t gets aligned at +8
+ */
+
+static const struct s_t {
+        int i;
+        int64_t j;
+} s;
+
+int main() {
+        if ((long)&s.j % 8 != 0) printf("non-aligned int64\n");
+        else printf("aligned int64\n");
+}
diff --git a/libs/libtpl-1.5/tests/malign.c b/libs/libtpl-1.5/tests/malign.c
new file mode 100755 (executable)
index 0000000..c3a3228
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+/* try compiling this with and without aligned doubles 
+ * 
+ * cc -malign-double -o malign malign.c
+ * cc -mno-align-double -o malign malign.c
+ * 
+ * on x86, double is not normally aligned (unless -malign-double is used).
+ * but on Sparc, or x86-64, double is aligned.
+ */
+
+static const struct s_t {
+        char a;
+        double d;
+} s;
+
+int main() {
+        if ((long)&s.d % 8 != 0) printf("-mno-align-double\n");
+        else printf("-malign-double\n");
+}
diff --git a/libs/libtpl-1.5/tests/mgwtest.c b/libs/libtpl-1.5/tests/mgwtest.c
new file mode 100755 (executable)
index 0000000..47528fc
--- /dev/null
@@ -0,0 +1,56 @@
+#include <windows.h>
+#include "tpl.h"
+
+int WINAPI WinMain (HINSTANCE hInstance, 
+                    HINSTANCE hPrevInstance, 
+                    PSTR szCmdLine, 
+                    int iCmdShow) 
+{
+  char *status;
+  int rc=0,i,j;
+  tpl_node *tn;
+  void *img;
+  size_t sz;
+
+  tn = tpl_map("A(i)", &i);
+  for(i=0; i<10; i++) tpl_pack(tn,1);
+  tpl_dump(tn,TPL_MEM,&img, &sz);
+  tpl_free(tn);
+
+  j=0;
+  tn = tpl_map("A(i)", &i);
+  tpl_load(tn,TPL_MEM,img,sz);
+  while(tpl_unpack(tn,1) > 0) {
+        if (i != j++) {
+           rc = -1;
+           break;
+        }
+  }
+  tpl_free(tn);
+
+  MessageBox (NULL, (rc==0)?"Test1 passed":"Test1 failed", 
+        "MinGW Tpl Test", MB_OK);
+
+  /* Test 2 */
+  tn = tpl_map("A(i)", &i);
+  for(i=0; i<10; i++) tpl_pack(tn,1);
+  tpl_dump(tn,TPL_FILE,"mgwtest.tpl");
+  tpl_free(tn);
+
+  j=0;
+  tn = tpl_map("A(i)", &i);
+  tpl_load(tn,TPL_FILE,"mgwtest.tpl");
+  while(tpl_unpack(tn,1) > 0) {
+        if (i != j++) {
+           rc = -1;
+           break;
+        }
+  }
+  tpl_free(tn);
+
+  MessageBox (NULL, (rc==0)?"Test2 passed":"Test2 failed", 
+        "MinGW Tpl Test", MB_OK);
+
+  return (0);
+}
+     
diff --git a/libs/libtpl-1.5/tests/other/Makefile b/libs/libtpl-1.5/tests/other/Makefile
new file mode 100755 (executable)
index 0000000..04cbb2d
--- /dev/null
@@ -0,0 +1,21 @@
+SRCDIR=../../src
+CPPFLAGS = -I$(SRCDIR)
+
+PROGS = other1
+all: $(PROGS) run_tests
+
+tpl.c: 
+       cp $(SRCDIR)/tpl.c .
+
+other1: other1.o tpl.o
+       g++ -o other1 other1.o tpl.o
+
+
+.PHONY: clean run_tests
+
+clean:
+       rm -f *.o $(PROGS) *.out
+       rm -f tpl.c
+
+run_tests:
+       perl ./do_tests
diff --git a/libs/libtpl-1.5/tests/other/README b/libs/libtpl-1.5/tests/other/README
new file mode 100755 (executable)
index 0000000..d3fd757
--- /dev/null
@@ -0,0 +1,2 @@
+Assorted other tests that are not part of the standard test suite.
+other1: a C++ program using "this" as a structure pointer
diff --git a/libs/libtpl-1.5/tests/other/do_tests b/libs/libtpl-1.5/tests/other/do_tests
new file mode 100755 (executable)
index 0000000..0b62640
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my @tests;
+for (glob "other*[0-9]") {
+    push @tests, $_ if -e "$_.ans";
+}
+
+my $num_failed=0;
+
+for my $test (@tests) {
+    `./$test > $test.out 2> $test.err`;
+    `diff $test.out $test.ans`;
+    print "$test failed\n" if $?;
+    $num_failed++ if $?;
+    unlink "$test.err" if -z "$test.err";
+}
+
+print scalar @tests . " tests conducted, $num_failed failed.\n";
+exit $num_failed;
diff --git a/libs/libtpl-1.5/tests/other/other1.ans b/libs/libtpl-1.5/tests/other/other1.ans
new file mode 100755 (executable)
index 0000000..f32671a
--- /dev/null
@@ -0,0 +1,3 @@
+buffer: tpl
+i: 9999
+c: this is a test string.
diff --git a/libs/libtpl-1.5/tests/other/other1.cpp b/libs/libtpl-1.5/tests/other/other1.cpp
new file mode 100755 (executable)
index 0000000..ce7f7ba
--- /dev/null
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <string.h>
+#include "tpl.h"
+main() {
+void *buffer;
+size_t bsize;
+       
+struct ci {
+    int i;
+    char c[30];
+       
+       void pack( void **buffer, size_t *size )
+       {
+               tpl_node *tn = tpl_map("S(ic#)", this, 30);  /* pass structure address */
+               tpl_pack(tn, 0);
+               tpl_dump(tn, TPL_MEM, buffer, size);
+               tpl_free(tn);
+       }
+       
+       void unpack( void *buffer, size_t size )
+       {
+               tpl_node *tn = tpl_map("S(ic#)", this, 30);
+               tpl_load(tn, TPL_MEM, buffer, size);
+               tpl_unpack( tn, 0 );
+               tpl_free(tn);
+       }
+};
+
+struct ci s = {9999, "this is a test string."};
+
+s.pack(&buffer, &bsize);
+printf("buffer: %s\n", (char *)buffer);
+
+struct ci b = { -1, "" };
+
+b.unpack(buffer, bsize);
+
+printf("i: %d\n", b.i);
+printf("c: %s\n", b.c);
+}
diff --git a/libs/libtpl-1.5/tests/sizes b/libs/libtpl-1.5/tests/sizes
new file mode 100755 (executable)
index 0000000..1c16449
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Config;
+
+#print "$_: ", ($Config{$_} or ""), "\n" for keys %Config;
+#exit;
+
+my @types = qw(char short int long longlong double);
+for (@types) {
+    my $bytes = $Config{"${_}size"};
+    my $bits = $bytes * 8;
+    printf "size of %-10s: %5d bytes (%d bits)\n", $_, $bytes, $bits;;
+}
+
+print qq/
+ These sizes reflect the platform and compiler options with
+ which Perl was built on this system. The sizes may change
+ if different compiler options are used.
+/;
+
diff --git a/libs/libtpl-1.5/tests/test1 b/libs/libtpl-1.5/tests/test1
new file mode 100755 (executable)
index 0000000..611d57a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test1 differ
diff --git a/libs/libtpl-1.5/tests/test1-mingw.c b/libs/libtpl-1.5/tests/test1-mingw.c
new file mode 100755 (executable)
index 0000000..1a1f20b
--- /dev/null
@@ -0,0 +1,12 @@
+#include <windows.h>
+#include "tpl.h"
+
+int WINAPI WinMain (HINSTANCE hInstance, 
+                    HINSTANCE hPrevInstance, 
+                    PSTR szCmdLine, 
+                    int iCmdShow) 
+{
+  MessageBox (NULL, "Hello", "Hello Demo", MB_OK);
+  return (0);
+}
+     
diff --git a/libs/libtpl-1.5/tests/test1.ans b/libs/libtpl-1.5/tests/test1.ans
new file mode 100755 (executable)
index 0000000..858b8f6
--- /dev/null
@@ -0,0 +1 @@
+j is 1
diff --git a/libs/libtpl-1.5/tests/test1.c b/libs/libtpl-1.5/tests/test1.c
new file mode 100755 (executable)
index 0000000..2e23fe4
--- /dev/null
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i,j=-1;
+    void *addr;
+    size_t sz;
+
+    tn = tpl_map("i",&i);
+    i=1;
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_MEM,&addr,&sz);
+    tpl_free(tn);
+
+    tn = tpl_map("i",&j);
+    tpl_load(tn,TPL_MEM,addr,sz);
+    tpl_unpack(tn,0);
+    printf("j is %d\n", j);
+    tpl_free(tn);
+    free(addr);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test1.out b/libs/libtpl-1.5/tests/test1.out
new file mode 100644 (file)
index 0000000..858b8f6
--- /dev/null
@@ -0,0 +1 @@
+j is 1
diff --git a/libs/libtpl-1.5/tests/test10 b/libs/libtpl-1.5/tests/test10
new file mode 100755 (executable)
index 0000000..a16c6d9
Binary files /dev/null and b/libs/libtpl-1.5/tests/test10 differ
diff --git a/libs/libtpl-1.5/tests/test10.ans b/libs/libtpl-1.5/tests/test10.ans
new file mode 100755 (executable)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test10.c b/libs/libtpl-1.5/tests/test10.c
new file mode 100755 (executable)
index 0000000..5e2bb03
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test10.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test10.out b/libs/libtpl-1.5/tests/test10.out
new file mode 100644 (file)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test10.tpl b/libs/libtpl-1.5/tests/test10.tpl
new file mode 100755 (executable)
index 0000000..a811f62
Binary files /dev/null and b/libs/libtpl-1.5/tests/test10.tpl differ
diff --git a/libs/libtpl-1.5/tests/test100 b/libs/libtpl-1.5/tests/test100
new file mode 100755 (executable)
index 0000000..b9d6dad
Binary files /dev/null and b/libs/libtpl-1.5/tests/test100 differ
diff --git a/libs/libtpl-1.5/tests/test100.ans b/libs/libtpl-1.5/tests/test100.ans
new file mode 100755 (executable)
index 0000000..402ddae
--- /dev/null
@@ -0,0 +1,2 @@
+fmt: S(ic)
+p: 1
diff --git a/libs/libtpl-1.5/tests/test100.c b/libs/libtpl-1.5/tests/test100.c
new file mode 100755 (executable)
index 0000000..ae34b46
--- /dev/null
@@ -0,0 +1,27 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename = "/tmp/test100.tpl";
+int main() {
+  tpl_node *tn;
+  struct {
+    int i;
+    char c;
+  } s;
+  int p;
+  char *fmt;
+
+  tn = tpl_map("S(ic)", &s);
+  s.i = 1; s.c = '^';
+  tpl_pack(tn, 0);
+  tpl_dump(tn, TPL_FILE, filename);
+  tpl_free(tn);
+
+  fmt = tpl_peek(TPL_FILE|TPL_DATAPEEK, filename, "i", &p);
+  if (fmt) {
+    printf("fmt: %s\n", fmt);
+    printf("p: %d\n", p);
+  }
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test100.out b/libs/libtpl-1.5/tests/test100.out
new file mode 100644 (file)
index 0000000..402ddae
--- /dev/null
@@ -0,0 +1,2 @@
+fmt: S(ic)
+p: 1
diff --git a/libs/libtpl-1.5/tests/test101 b/libs/libtpl-1.5/tests/test101
new file mode 100755 (executable)
index 0000000..ce27466
Binary files /dev/null and b/libs/libtpl-1.5/tests/test101 differ
diff --git a/libs/libtpl-1.5/tests/test101.ans b/libs/libtpl-1.5/tests/test101.ans
new file mode 100755 (executable)
index 0000000..68bece6
--- /dev/null
@@ -0,0 +1,2 @@
+TPL_DATAPEEK format mismatches tpl iamge
+peek failed
diff --git a/libs/libtpl-1.5/tests/test101.c b/libs/libtpl-1.5/tests/test101.c
new file mode 100755 (executable)
index 0000000..833657a
--- /dev/null
@@ -0,0 +1,30 @@
+#include "tpl.h"
+#include <stdio.h>
+
+extern tpl_hook_t tpl_hook;
+const char *filename = "/tmp/test101.tpl";
+int main() {
+  tpl_node *tn;
+  struct {
+    int i;
+    char c;
+  } s;
+  char *fmt, q;
+  tpl_hook.oops = printf;
+
+  tn = tpl_map("S(ic)", &s);
+  s.i = 1; s.c = '^';
+  tpl_pack(tn, 0);
+  tpl_dump(tn, TPL_FILE, filename);
+  tpl_free(tn);
+
+  fmt = tpl_peek(TPL_FILE|TPL_DATAPEEK, filename, "c", &q);
+  if (fmt) {
+    printf("fmt: %s\n", fmt);
+    printf("q: %c\n", q);
+  } else {
+    printf("peek failed\n");
+  }
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test101.out b/libs/libtpl-1.5/tests/test101.out
new file mode 100644 (file)
index 0000000..68bece6
--- /dev/null
@@ -0,0 +1,2 @@
+TPL_DATAPEEK format mismatches tpl iamge
+peek failed
diff --git a/libs/libtpl-1.5/tests/test102 b/libs/libtpl-1.5/tests/test102
new file mode 100755 (executable)
index 0000000..c5e6804
Binary files /dev/null and b/libs/libtpl-1.5/tests/test102 differ
diff --git a/libs/libtpl-1.5/tests/test102.ans b/libs/libtpl-1.5/tests/test102.ans
new file mode 100755 (executable)
index 0000000..a29caa7
--- /dev/null
@@ -0,0 +1,2 @@
+fmt: c
+q: !
diff --git a/libs/libtpl-1.5/tests/test102.c b/libs/libtpl-1.5/tests/test102.c
new file mode 100755 (executable)
index 0000000..0b8fd8c
--- /dev/null
@@ -0,0 +1,22 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename = "/tmp/test102.tpl";
+int main() {
+  tpl_node *tn;
+  char *fmt,p,q;
+
+  tn = tpl_map("c", &p);
+  p = '!';
+  tpl_pack(tn, 0);
+  tpl_dump(tn, TPL_FILE, filename);
+  tpl_free(tn);
+
+  fmt = tpl_peek(TPL_FILE|TPL_DATAPEEK, filename, "c", &q);
+  if (fmt) {
+    printf("fmt: %s\n", fmt);
+    printf("q: %c\n", q);
+  }
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test102.out b/libs/libtpl-1.5/tests/test102.out
new file mode 100644 (file)
index 0000000..a29caa7
--- /dev/null
@@ -0,0 +1,2 @@
+fmt: c
+q: !
diff --git a/libs/libtpl-1.5/tests/test103 b/libs/libtpl-1.5/tests/test103
new file mode 100755 (executable)
index 0000000..a2c1618
Binary files /dev/null and b/libs/libtpl-1.5/tests/test103 differ
diff --git a/libs/libtpl-1.5/tests/test103.ans b/libs/libtpl-1.5/tests/test103.ans
new file mode 100755 (executable)
index 0000000..3763fdf
--- /dev/null
@@ -0,0 +1,2 @@
+fmt: S(iscsiu)
+pi: 1, ps: hello, pc: ^, pt: world, pi: 2
diff --git a/libs/libtpl-1.5/tests/test103.c b/libs/libtpl-1.5/tests/test103.c
new file mode 100755 (executable)
index 0000000..006b388
--- /dev/null
@@ -0,0 +1,33 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename = "/tmp/test103.tpl";
+int main() {
+  tpl_node *tn;
+  struct {
+    int i;
+    char *s;
+    char c;
+    char *t;
+    int j;
+    unsigned u;
+  } s;
+  char *fmt, *ps, pc, *pt;
+  int pi, pj;
+
+  tn = tpl_map("S(iscsiu)", &s);
+  s.i = 1; s.s = "hello"; s.c = '^'; s.t = "world"; s.j = 2; s.u = 3;
+  tpl_pack(tn, 0);
+  tpl_dump(tn, TPL_FILE, filename);
+  tpl_free(tn);
+
+  fmt = tpl_peek(TPL_FILE|TPL_DATAPEEK, filename, "iscsi",&pi,&ps,&pc,&pt,&pj);
+  if (fmt) {
+    printf("fmt: %s\n", fmt);
+    printf("pi: %d, ps: %s, pc: %c, pt: %s, pi: %d\n", pi,ps,pc,pt,pj);
+  } else {
+    printf("peek failed\n");
+  }
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test103.out b/libs/libtpl-1.5/tests/test103.out
new file mode 100644 (file)
index 0000000..3763fdf
--- /dev/null
@@ -0,0 +1,2 @@
+fmt: S(iscsiu)
+pi: 1, ps: hello, pc: ^, pt: world, pi: 2
diff --git a/libs/libtpl-1.5/tests/test104 b/libs/libtpl-1.5/tests/test104
new file mode 100755 (executable)
index 0000000..10be0c7
Binary files /dev/null and b/libs/libtpl-1.5/tests/test104 differ
diff --git a/libs/libtpl-1.5/tests/test104.ans b/libs/libtpl-1.5/tests/test104.ans
new file mode 100755 (executable)
index 0000000..5e79c69
--- /dev/null
@@ -0,0 +1,2 @@
+fmt: S(iscsiu)
+pi: 1, ps: NULL, pc: ^, pt: world, pi: 2
diff --git a/libs/libtpl-1.5/tests/test104.c b/libs/libtpl-1.5/tests/test104.c
new file mode 100755 (executable)
index 0000000..9c2e309
--- /dev/null
@@ -0,0 +1,33 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename = "/tmp/test104.tpl";
+int main() {
+  tpl_node *tn;
+  struct {
+    int i;
+    char *s;
+    char c;
+    char *t;
+    int j;
+    unsigned u;
+  } s;
+  char *fmt, *ps, pc, *pt;
+  int pi, pj;
+
+  tn = tpl_map("S(iscsiu)", &s);
+  s.i = 1; s.s = NULL; s.c = '^'; s.t = "world"; s.j = 2; s.u = 3;
+  tpl_pack(tn, 0);
+  tpl_dump(tn, TPL_FILE, filename);
+  tpl_free(tn);
+
+  fmt = tpl_peek(TPL_FILE|TPL_DATAPEEK, filename, "iscsi",&pi,&ps,&pc,&pt,&pj);
+  if (fmt) {
+    printf("fmt: %s\n", fmt);
+    printf("pi: %d, ps: %s, pc: %c, pt: %s, pi: %d\n",pi,ps?ps:"NULL",pc,pt,pj);
+  } else {
+    printf("peek failed\n");
+  }
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test104.out b/libs/libtpl-1.5/tests/test104.out
new file mode 100644 (file)
index 0000000..5e79c69
--- /dev/null
@@ -0,0 +1,2 @@
+fmt: S(iscsiu)
+pi: 1, ps: NULL, pc: ^, pt: world, pi: 2
diff --git a/libs/libtpl-1.5/tests/test105 b/libs/libtpl-1.5/tests/test105
new file mode 100755 (executable)
index 0000000..abeb3d1
Binary files /dev/null and b/libs/libtpl-1.5/tests/test105 differ
diff --git a/libs/libtpl-1.5/tests/test105.ans b/libs/libtpl-1.5/tests/test105.ans
new file mode 100755 (executable)
index 0000000..811209f
--- /dev/null
@@ -0,0 +1,2 @@
+i: 1, s: hello, w: world, c: $
+i: 1, s: hello, w: world, c: $
diff --git a/libs/libtpl-1.5/tests/test105.c b/libs/libtpl-1.5/tests/test105.c
new file mode 100755 (executable)
index 0000000..c8e6411
--- /dev/null
@@ -0,0 +1,29 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename = "/tmp/test105.tpl";
+
+int main() {
+  int i=1;
+  char *s="hello",*w="world",c='$', *fmt;
+  tpl_node *tn;
+
+  tpl_jot(TPL_FILE, filename, "issc", &i, &s, &w, &c);
+
+  i = 0; s = NULL; w = NULL; c = 0;
+
+  /* unpack the normal way */
+  tn = tpl_map("issc", &i, &s, &w, &c);
+  tpl_load(tn, TPL_FILE, filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+  printf("i: %d, s: %s, w: %s, c: %c\n", i, s, w, c);
+
+  i = 0; s = NULL; w = NULL; c = 0;
+
+  /* unpack the quick way */
+  fmt = tpl_peek(TPL_FILE|TPL_DATAPEEK, filename, "issc", &i, &s, &w, &c);
+  printf("i: %d, s: %s, w: %s, c: %c\n", i, s, w, c);
+  
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test105.out b/libs/libtpl-1.5/tests/test105.out
new file mode 100644 (file)
index 0000000..811209f
--- /dev/null
@@ -0,0 +1,2 @@
+i: 1, s: hello, w: world, c: $
+i: 1, s: hello, w: world, c: $
diff --git a/libs/libtpl-1.5/tests/test106 b/libs/libtpl-1.5/tests/test106
new file mode 100755 (executable)
index 0000000..5eb1331
Binary files /dev/null and b/libs/libtpl-1.5/tests/test106 differ
diff --git a/libs/libtpl-1.5/tests/test106.ans b/libs/libtpl-1.5/tests/test106.ans
new file mode 100755 (executable)
index 0000000..e8aff5b
--- /dev/null
@@ -0,0 +1,24 @@
+testing with TPL_FILE:
+1000
+  0, 0, 0, 5000, 15, Deepak
+  1, 5, 10, 6000, 18, Deepak
+  2, 10, 20, 7000, 21, Deepak
+  3, 15, 30, 8000, 24, Deepak
+  4, 20, 40, 9000, 27, Deepak
+  5, 25, 50, 10000, 30, Deepak
+  6, 30, 60, 11000, 33, Deepak
+  7, 35, 70, 12000, 36, Deepak
+  8, 40, 80, 13000, 39, Deepak
+9,23,43,16
+testing with TPL_FD:
+1000
+  0, 0, 0, 5000, 15, Deepak
+  1, 5, 10, 6000, 18, Deepak
+  2, 10, 20, 7000, 21, Deepak
+  3, 15, 30, 8000, 24, Deepak
+  4, 20, 40, 9000, 27, Deepak
+  5, 25, 50, 10000, 30, Deepak
+  6, 30, 60, 11000, 33, Deepak
+  7, 35, 70, 12000, 36, Deepak
+  8, 40, 80, 13000, 39, Deepak
+9,23,43,16
diff --git a/libs/libtpl-1.5/tests/test106.c b/libs/libtpl-1.5/tests/test106.c
new file mode 100755 (executable)
index 0000000..ea0ef45
--- /dev/null
@@ -0,0 +1,126 @@
+#include "tpl.h"
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define SUM_LENGTH 16 
+#define MS_COUNT 9 
+struct sum_buf {
+    int64_t offset;
+    int len;  
+    uint32_t sum1;       
+    int chain; 
+    uint16_t flags; 
+    char sum2[SUM_LENGTH]; 
+};
+struct sum_struct {
+    int64_t flength;
+    struct sum_buf *sums; 
+    int count; 
+    int blength; 
+    int remainder;
+    int s2length;  
+};
+const char *filename =  "/tmp/test106.tpl"; 
+
+int pack(int use_fd)  
+{
+    tpl_node *tn;
+    struct sum_struct ms;
+    int fd=-1,j;
+    unsigned perms;
+    
+     perms = S_IRUSR|S_IWUSR; 
+     if (use_fd) {
+       if ( (fd=open( filename,O_WRONLY|O_CREAT,perms)) == -1) {
+           printf("failed to open %s: %s", filename, strerror(errno));
+           return(-1);
+       }
+     }
+     ms.flength = 1000;
+     ms.count = MS_COUNT;
+     ms.blength = 23;
+     ms.remainder = 43;
+     ms.s2length = 16;
+     ms.sums = (struct sum_buf*) malloc((sizeof(struct sum_buf))*ms.count);
+    for(j=0;j<ms.count;j++)
+    {
+        ms.sums[j].offset = (uint64_t) j;
+        ms.sums[j].len = j*5;
+        ms.sums[j].sum1 = j*10;
+        ms.sums[j].chain = j*1000+5000;
+        ms.sums[j].flags = j*3 + 15; 
+        memset(ms.sums[j].sum2,0,SUM_LENGTH); 
+        strcpy(ms.sums[j].sum2,"Deepak");
+    }
+    tn = tpl_map( "IS(Iiuijc#)#iiii", &ms.flength,ms.sums,SUM_LENGTH,
+      ms.count,&ms.count,&ms.blength,&ms.remainder,&ms.s2length);
+    tpl_pack( tn, 0 );
+
+    if (use_fd) {
+      tpl_dump(tn,TPL_FD, fd); 
+      close(fd);
+    } else {
+      tpl_dump(tn,TPL_FILE,filename);  
+    }
+
+    tpl_free( tn );
+    
+    return 0;
+}
+int unpack(int use_fd) {
+    tpl_node *tn;
+    struct sum_struct ms;
+    unsigned perms;
+    int fd=-1,i;
+    perms = S_IRUSR|S_IWUSR; 
+    if (use_fd) {
+      if ( (fd=open( filename,O_RDONLY,perms)) == -1) {
+          printf("failed to open %s: %s", filename, strerror(errno));
+          return(-1);
+      }
+    }
+    ms.sums = (struct sum_buf*) malloc((sizeof(struct sum_buf))*MS_COUNT);
+    tn = tpl_map( "IS(Iiuijc#)#iiii", &ms.flength,ms.sums,SUM_LENGTH,
+      MS_COUNT,&ms.count,&ms.blength,&ms.remainder,&ms.s2length);
+    if (use_fd) tpl_load(tn, TPL_FD, fd);
+    else tpl_load(tn, TPL_FILE, filename);
+    tpl_unpack(tn, 0 );
+    tpl_free( tn );
+    if (use_fd) close(fd);
+
+    printf("%d\n", (int)(ms.flength)); 
+    for(i=0; i < MS_COUNT; i++) {
+      printf("  %d, %d, %u, %d, %d, %s\n", (int)(ms.sums[i].offset), ms.sums[i].len, ms.sums[i].sum1, ms.sums[i].chain, (int)(ms.sums[i].flags), ms.sums[i].sum2);
+    }
+    printf("%d,%d,%d,%d\n", ms.count, ms.blength, ms.remainder, ms.s2length);
+    return 0;
+}
+int main() {
+  printf("testing with TPL_FILE:\n");
+  pack(0);
+  unpack(0);
+
+  printf("testing with TPL_FD:\n");
+  pack(1);
+  unpack(1);
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test106.out b/libs/libtpl-1.5/tests/test106.out
new file mode 100644 (file)
index 0000000..e8aff5b
--- /dev/null
@@ -0,0 +1,24 @@
+testing with TPL_FILE:
+1000
+  0, 0, 0, 5000, 15, Deepak
+  1, 5, 10, 6000, 18, Deepak
+  2, 10, 20, 7000, 21, Deepak
+  3, 15, 30, 8000, 24, Deepak
+  4, 20, 40, 9000, 27, Deepak
+  5, 25, 50, 10000, 30, Deepak
+  6, 30, 60, 11000, 33, Deepak
+  7, 35, 70, 12000, 36, Deepak
+  8, 40, 80, 13000, 39, Deepak
+9,23,43,16
+testing with TPL_FD:
+1000
+  0, 0, 0, 5000, 15, Deepak
+  1, 5, 10, 6000, 18, Deepak
+  2, 10, 20, 7000, 21, Deepak
+  3, 15, 30, 8000, 24, Deepak
+  4, 20, 40, 9000, 27, Deepak
+  5, 25, 50, 10000, 30, Deepak
+  6, 30, 60, 11000, 33, Deepak
+  7, 35, 70, 12000, 36, Deepak
+  8, 40, 80, 13000, 39, Deepak
+9,23,43,16
diff --git a/libs/libtpl-1.5/tests/test107 b/libs/libtpl-1.5/tests/test107
new file mode 100755 (executable)
index 0000000..d886133
Binary files /dev/null and b/libs/libtpl-1.5/tests/test107 differ
diff --git a/libs/libtpl-1.5/tests/test107.ans b/libs/libtpl-1.5/tests/test107.ans
new file mode 100755 (executable)
index 0000000..02bf39a
--- /dev/null
@@ -0,0 +1,5 @@
+0 cat
+1 dog
+2 eel
+3 emu
+4 ant
diff --git a/libs/libtpl-1.5/tests/test107.c b/libs/libtpl-1.5/tests/test107.c
new file mode 100755 (executable)
index 0000000..e936e27
--- /dev/null
@@ -0,0 +1,38 @@
+#include "tpl.h"
+#include <stdio.h>
+#include <string.h>
+
+typedef struct {
+  int i;
+  char c[4];
+} test_t;
+
+const char *filename = "/tmp/test107.tpl";
+
+int main() {
+  test_t s[5], t[5];
+  tpl_node *tn;
+  int i;
+
+  s[0].i = 0; strcpy(s[0].c, "cat");
+  s[1].i = 1; strcpy(s[1].c, "dog");
+  s[2].i = 2; strcpy(s[2].c, "eel");
+  s[3].i = 3; strcpy(s[3].c, "emu");
+  s[4].i = 4; strcpy(s[4].c, "ant");
+
+  tn = tpl_map("S(ic#)#", &s, 4, 5);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("S(ic#)#", &t, 4, 5);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  for(i=0; i < 5; i++) {
+    printf("%d %s\n", s[i].i, s[i].c);
+  }
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test107.out b/libs/libtpl-1.5/tests/test107.out
new file mode 100644 (file)
index 0000000..02bf39a
--- /dev/null
@@ -0,0 +1,5 @@
+0 cat
+1 dog
+2 eel
+3 emu
+4 ant
diff --git a/libs/libtpl-1.5/tests/test108 b/libs/libtpl-1.5/tests/test108
new file mode 100755 (executable)
index 0000000..df948b4
Binary files /dev/null and b/libs/libtpl-1.5/tests/test108 differ
diff --git a/libs/libtpl-1.5/tests/test108.ans b/libs/libtpl-1.5/tests/test108.ans
new file mode 100755 (executable)
index 0000000..ff0ab00
--- /dev/null
@@ -0,0 +1,2 @@
+structure matches original
+other fields match original
diff --git a/libs/libtpl-1.5/tests/test108.c b/libs/libtpl-1.5/tests/test108.c
new file mode 100755 (executable)
index 0000000..5a12589
--- /dev/null
@@ -0,0 +1,49 @@
+#include "tpl.h"
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+typedef struct {
+  int64_t j;
+  int l1;
+  unsigned l2;
+  int i;
+  int16_t h;
+  char c[4];
+} test_t;
+
+const char *filename = "/tmp/test108.tpl";
+
+int main() {
+  test_t s[5], t[5];
+  tpl_node *tn;
+  int w=10,x=20,y=30,z=40,W,X,Y,Z;
+  uint64_t b=10,B;
+
+  memset(s, 0, sizeof(s));
+  memset(t, 0, sizeof(t));
+
+  s[0].j=0;   s[0].i=0; s[0].l1= 0; s[0].l2=0;  s[0].h=   0; strcpy(s[0].c, "cat");
+  s[1].j=100; s[1].i=1; s[1].l1=-1; s[1].l2=10; s[1].h=1000; strcpy(s[1].c, "dog");
+  s[2].j=200; s[2].i=2; s[2].l1=-2; s[2].l2=20; s[2].h=2000; strcpy(s[2].c, "eel");
+  s[3].j=300; s[3].i=3; s[3].l1=-3; s[3].l2=30; s[3].h=3000; strcpy(s[3].c, "emu");
+  s[4].j=400; s[4].i=4; s[4].l1=-4; s[4].l2=40; s[4].h=4000; strcpy(s[4].c, "ant");
+
+  tn = tpl_map("IS(Iiuijc#)#iiii", &b, s, 4, 5, &w, &x, &y, &z);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("IS(Iiuijc#)#iiii", &B, t, 4, 5, &W, &X, &Y, &Z);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  if (memcmp(t,s,sizeof(t)) == 0) printf("structure matches original\n");
+  else printf("structure mismatches original\n");
+
+  if (b==B && w==W && x==X && y==Y && z==Z) printf("other fields match original\n");
+  else printf("other fields mismatch originals\n");
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test108.out b/libs/libtpl-1.5/tests/test108.out
new file mode 100644 (file)
index 0000000..ff0ab00
--- /dev/null
@@ -0,0 +1,2 @@
+structure matches original
+other fields match original
diff --git a/libs/libtpl-1.5/tests/test109 b/libs/libtpl-1.5/tests/test109
new file mode 100755 (executable)
index 0000000..70813e3
Binary files /dev/null and b/libs/libtpl-1.5/tests/test109 differ
diff --git a/libs/libtpl-1.5/tests/test109.ans b/libs/libtpl-1.5/tests/test109.ans
new file mode 100755 (executable)
index 0000000..0515356
--- /dev/null
@@ -0,0 +1,2 @@
+sizeof(s): 12
+structures match
diff --git a/libs/libtpl-1.5/tests/test109.c b/libs/libtpl-1.5/tests/test109.c
new file mode 100755 (executable)
index 0000000..616f048
--- /dev/null
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include "tpl.h"
+#include <inttypes.h>
+
+const char *filename = "/tmp/test109.tpl";
+
+typedef struct {
+  char c;
+  uint32_t i;
+  uint16_t j;
+  char d;
+} spad;
+
+int main() {
+  tpl_node *tn;
+  spad s = {'a', 1, 2, 'b'}, t = {'?', 0, 0, '!'};;
+
+  printf("sizeof(s): %d\n", (int)sizeof(s));;
+  tn = tpl_map("S(cijc)", &s);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("S(cijc)", &t);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  if (s.c==t.c && s.i==t.i && s.j==t.j && s.d==t.d) 
+    printf("structures match\n");
+  else
+    printf("structures mismatch\n");
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test109.out b/libs/libtpl-1.5/tests/test109.out
new file mode 100644 (file)
index 0000000..0515356
--- /dev/null
@@ -0,0 +1,2 @@
+sizeof(s): 12
+structures match
diff --git a/libs/libtpl-1.5/tests/test11 b/libs/libtpl-1.5/tests/test11
new file mode 100755 (executable)
index 0000000..06ad4ff
Binary files /dev/null and b/libs/libtpl-1.5/tests/test11 differ
diff --git a/libs/libtpl-1.5/tests/test11.ans b/libs/libtpl-1.5/tests/test11.ans
new file mode 100755 (executable)
index 0000000..c54ecf7
--- /dev/null
@@ -0,0 +1 @@
+test11.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test11.c b/libs/libtpl-1.5/tests/test11.c
new file mode 100755 (executable)
index 0000000..efe5b18
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test11.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test11.out b/libs/libtpl-1.5/tests/test11.out
new file mode 100644 (file)
index 0000000..c54ecf7
--- /dev/null
@@ -0,0 +1 @@
+test11.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test11.tpl b/libs/libtpl-1.5/tests/test11.tpl
new file mode 100755 (executable)
index 0000000..d3a3e3d
Binary files /dev/null and b/libs/libtpl-1.5/tests/test11.tpl differ
diff --git a/libs/libtpl-1.5/tests/test110 b/libs/libtpl-1.5/tests/test110
new file mode 100755 (executable)
index 0000000..790c293
Binary files /dev/null and b/libs/libtpl-1.5/tests/test110 differ
diff --git a/libs/libtpl-1.5/tests/test110.ans b/libs/libtpl-1.5/tests/test110.ans
new file mode 100755 (executable)
index 0000000..3d6e6e2
--- /dev/null
@@ -0,0 +1 @@
+structures match
diff --git a/libs/libtpl-1.5/tests/test110.c b/libs/libtpl-1.5/tests/test110.c
new file mode 100755 (executable)
index 0000000..3e81214
--- /dev/null
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tpl.h"
+#include <inttypes.h>
+
+const char *filename = "/tmp/test110.tpl";
+
+int nstrcmp(const char *a, const char *b) {
+  if (a==NULL || b==NULL) return (a==NULL && b==NULL)?0:1;
+  return strcmp(a,b);
+}
+
+int main() {
+  tpl_node *tn;
+
+  char *s1,*s2,*s3,*s4;
+  int i5,i6,i7,i8,i9,
+      i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,
+      i21,i22,i23,i24,i25,i26,i27,i28,i29,i30,i31,i32,i33;
+  double f34,f35,f36;
+  int i37,i38,i39,i40;
+
+  char *S1,*S2,*S3,*S4;
+  int I5,I6,I7,I8,I9,
+      I10,I11,I12,I13,I14,I15,I16,I17,I18,I19,I20,
+      I21,I22,I23,I24,I25,I26,I27,I28,I29,I30,I31,I32,I33;
+  double F34,F35,F36;
+  int I37,I38,I39,I40;
+
+  s1=NULL;s2=NULL;s3="testing";s4="some_string";
+  i5=5;i6=6;i7=7;i8=8;i9=9;
+  i10=10;i11=11;i12=12;i13=13;i14=14;i15=15;i16=16;i17=17;i18=18;i19=19;i20=20;
+  i21=21;i22=22;i23=23;i24=24;i25=25;i26=26;i27=27;i28=28;i29=29;i30=30;i31=31;
+  i32=32;i33=33;
+  f34=34.0;f35=35.0;f36=36.0;
+  i37=37;i38=38;i39=39;i40=40;
+
+
+  tn = tpl_map("ssssiiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiii", 
+              &s1,&s2,&s3,&s4,
+              &i5,&i6,&i7,&i8,&i9,
+              &i10,&i11,&i12,&i13,&i14,&i15,&i16,&i17,&i18,&i19,&i20,
+              &i21,&i22,&i23,&i24,&i25,&i26,&i27,&i28,&i29,&i30,&i31,&i32,&i33,
+              &f34,&f35,&f36,
+              &i37,&i38,&i39,&i40);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("ssssiiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiii", 
+              &S1,&S2,&S3,&S4,
+              &I5,&I6,&I7,&I8,&I9,
+              &I10,&I11,&I12,&I13,&I14,&I15,&I16,&I17,&I18,&I19,&I20,
+              &I21,&I22,&I23,&I24,&I25,&I26,&I27,&I28,&I29,&I30,&I31,&I32,&I33,
+              &F34,&F35,&F36,
+              &I37,&I38,&I39,&I40);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  if (
+    !nstrcmp(s1,S1) && !nstrcmp(s2,S2) && !nstrcmp(s3,S3) && !nstrcmp(s4,S4) &&
+    i5==I5 && i6==I6 && i7==I7 && i8==I8 && i9==I9 && i10==I10 && i11==I11 &&
+    i12==I12 && i13==I13 && i14==I14 && i15==I15 && i16==I16 && i17==I17 &&
+    i18==I18 && i19==I19 && i20==I20 && i21==I21 && i22==I22 && i23==I23 &&
+    i24==I24 && i25==I25 && i26==I26 && i27==I27 && i28==I28 && i29==I29 &&
+    i30==I30 && i31==I31 && i32==I32 && i33==I33 && f34==F34 && f35==F35 &&
+    f36==F36 && i37==I37 && i38==I38 && i39==I39 && i40==I40
+    ) {
+    printf("structures match\n");
+    free(S1); free(S2); free(S3); free(S4);
+  }
+  else
+    printf("structures mismatch\n");
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test110.out b/libs/libtpl-1.5/tests/test110.out
new file mode 100644 (file)
index 0000000..3d6e6e2
--- /dev/null
@@ -0,0 +1 @@
+structures match
diff --git a/libs/libtpl-1.5/tests/test111 b/libs/libtpl-1.5/tests/test111
new file mode 100755 (executable)
index 0000000..d0b7213
Binary files /dev/null and b/libs/libtpl-1.5/tests/test111 differ
diff --git a/libs/libtpl-1.5/tests/test111.ans b/libs/libtpl-1.5/tests/test111.ans
new file mode 100755 (executable)
index 0000000..3d6e6e2
--- /dev/null
@@ -0,0 +1 @@
+structures match
diff --git a/libs/libtpl-1.5/tests/test111.c b/libs/libtpl-1.5/tests/test111.c
new file mode 100755 (executable)
index 0000000..c03082d
--- /dev/null
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "tpl.h"
+
+const char *filename = "/tmp/test111.tpl";
+
+#define NUM 100
+
+struct st {
+  int i;
+  char c;
+  double f;
+  uint16_t v[2];
+};
+
+
+int main() {
+  struct st s[NUM], d[NUM];
+  tpl_node *tn; 
+  int i;
+
+  memset(s, 0, sizeof(s)); /* clear s */
+  memset(d, 0, sizeof(d)); /* clear d */
+
+  /* fill s with random stuff */
+  for(i=0; i < NUM; i++) {
+    s[i].i = i; s[i].c='a'+i; s[i].f = 3.14159 * i; s[i].v[0] = NUM*i; s[i].v[1] = NUM+i; 
+  }
+
+  tn = tpl_map("S(icfv#)#", s, 2, NUM);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("S(icfv#)#", d, 2, NUM);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  /* see if the result is the same as the s */
+  printf("structures %s\n", (!memcmp(d,s,sizeof(d)))? "match" : "mismatch");
+  return 0;
+}
+
diff --git a/libs/libtpl-1.5/tests/test111.out b/libs/libtpl-1.5/tests/test111.out
new file mode 100644 (file)
index 0000000..3d6e6e2
--- /dev/null
@@ -0,0 +1 @@
+structures match
diff --git a/libs/libtpl-1.5/tests/test112 b/libs/libtpl-1.5/tests/test112
new file mode 100755 (executable)
index 0000000..b1336df
Binary files /dev/null and b/libs/libtpl-1.5/tests/test112 differ
diff --git a/libs/libtpl-1.5/tests/test112.ans b/libs/libtpl-1.5/tests/test112.ans
new file mode 100755 (executable)
index 0000000..3d6e6e2
--- /dev/null
@@ -0,0 +1 @@
+structures match
diff --git a/libs/libtpl-1.5/tests/test112.c b/libs/libtpl-1.5/tests/test112.c
new file mode 100755 (executable)
index 0000000..4dd8402
--- /dev/null
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "tpl.h"
+
+const char *filename = "/tmp/test112.tpl";
+
+#define NUM 10
+
+struct st {
+  int i;
+  char c[8];
+  double f;
+  uint16_t v[2];
+};
+
+
+int main() {
+  struct st s[NUM], d[NUM];
+  tpl_node *tn; 
+  int i;
+
+  memset(s, 0, sizeof(s)); /* clear s */
+  memset(d, 0, sizeof(d)); /* clear d */
+
+  /* fill s with random stuff */
+  for(i=0; i < NUM; i++) {
+    s[i].i = i; s[i].f = 3.14159 * i; s[i].v[0] = NUM*i; s[i].v[1] = NUM+i; 
+    strncpy(s[i].c, "abcdefg",8);
+    s[i].c[0] += 1;
+  }
+
+  tn = tpl_map("S(ic#fv#)#", s, 8, 2, NUM);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("S(ic#fv#)#", d, 8, 2, NUM);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  /* see if the result is the same as the s */
+  printf("structures %s\n", (!memcmp(d,s,sizeof(d)))? "match" : "mismatch");
+  return 0;
+}
+
diff --git a/libs/libtpl-1.5/tests/test112.out b/libs/libtpl-1.5/tests/test112.out
new file mode 100644 (file)
index 0000000..3d6e6e2
--- /dev/null
@@ -0,0 +1 @@
+structures match
diff --git a/libs/libtpl-1.5/tests/test113 b/libs/libtpl-1.5/tests/test113
new file mode 100755 (executable)
index 0000000..cb384ef
Binary files /dev/null and b/libs/libtpl-1.5/tests/test113 differ
diff --git a/libs/libtpl-1.5/tests/test113.ans b/libs/libtpl-1.5/tests/test113.ans
new file mode 100755 (executable)
index 0000000..a317aed
--- /dev/null
@@ -0,0 +1,5 @@
+structures match
+A matches
+B matches
+C matches
+D matches
diff --git a/libs/libtpl-1.5/tests/test113.c b/libs/libtpl-1.5/tests/test113.c
new file mode 100755 (executable)
index 0000000..3cf827e
--- /dev/null
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "tpl.h"
+
+const char *filename = "/tmp/test113.tpl";
+
+#define NUM 10
+
+struct st {
+  int i;
+  char c[8];
+  double f;
+  uint16_t v[2];
+};
+
+
+int main() {
+  struct st s[NUM], t[NUM];
+  tpl_node *tn; 
+  int i;
+  int a=5,d=8, A, D;
+  char b='6',c='7', B, C;
+
+  memset(s, 0, sizeof(s)); /* clear s */
+  memset(t, 0, sizeof(t)); /* clear t */
+
+  /* fill s with random stuff */
+  for(i=0; i < NUM; i++) {
+    s[i].i = i; s[i].f = 3.14159 * i; s[i].v[0] = NUM*i; s[i].v[1] = NUM+i; 
+    strncpy(s[i].c, "abcdefg",8);
+    s[i].c[0] += 1;
+  }
+
+  tn = tpl_map("icS(ic#fv#)#ci", &a, &b, s, 8, 2, NUM, &c, &d);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("icS(ic#fv#)#ci", &A, &B, t, 8, 2, NUM, &C, &D);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  /* see if the result is the same as the s */
+  printf("structures %s\n", (!memcmp(t,s,sizeof(d)))? "match" : "mismatch");
+  printf("A %s\n", (a==A)? "matches" : "mismatches");
+  printf("B %s\n", (b==B)? "matches" : "mismatches");
+  printf("C %s\n", (c==C)? "matches" : "mismatches");
+  printf("D %s\n", (d==D)? "matches" : "mismatches");
+  return 0;
+}
+
diff --git a/libs/libtpl-1.5/tests/test113.out b/libs/libtpl-1.5/tests/test113.out
new file mode 100644 (file)
index 0000000..a317aed
--- /dev/null
@@ -0,0 +1,5 @@
+structures match
+A matches
+B matches
+C matches
+D matches
diff --git a/libs/libtpl-1.5/tests/test114 b/libs/libtpl-1.5/tests/test114
new file mode 100755 (executable)
index 0000000..dfd7bf6
Binary files /dev/null and b/libs/libtpl-1.5/tests/test114 differ
diff --git a/libs/libtpl-1.5/tests/test114.ans b/libs/libtpl-1.5/tests/test114.ans
new file mode 100755 (executable)
index 0000000..4ed9d2a
--- /dev/null
@@ -0,0 +1 @@
+matrices match
diff --git a/libs/libtpl-1.5/tests/test114.c b/libs/libtpl-1.5/tests/test114.c
new file mode 100755 (executable)
index 0000000..228f0c8
--- /dev/null
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <string.h>
+#include "tpl.h"
+
+#define XDIM 10
+#define YDIM 2
+
+const char *filename = "/tmp/test114.tpl";
+extern tpl_hook_t tpl_hook;
+
+int main() {
+  tpl_node *tn;
+  int xy[XDIM][YDIM], XY[XDIM][YDIM];
+  int i,j;
+
+  tpl_hook.oops = printf;
+
+  for(i=0; i<XDIM; i++) {
+    for(j=0; j<YDIM; j++) {
+      xy[i][j] = i+j;
+      XY[i][j] = 0;
+    }
+  }
+
+  tn = tpl_map("i##", xy, XDIM, YDIM);
+  if (!tn) {
+    printf("tpl_map failed; exiting\n");
+    return -1;
+  }
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("i##", XY, XDIM, YDIM);
+  if (!tn) {
+    printf("tpl_map failed; exiting\n");
+    return -1;
+  }
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  printf("matrices %s\n", (!memcmp(xy,XY,sizeof(xy))) ?  "match" : "mismatch");
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test114.out b/libs/libtpl-1.5/tests/test114.out
new file mode 100644 (file)
index 0000000..4ed9d2a
--- /dev/null
@@ -0,0 +1 @@
+matrices match
diff --git a/libs/libtpl-1.5/tests/test115 b/libs/libtpl-1.5/tests/test115
new file mode 100755 (executable)
index 0000000..5c295be
Binary files /dev/null and b/libs/libtpl-1.5/tests/test115 differ
diff --git a/libs/libtpl-1.5/tests/test115.ans b/libs/libtpl-1.5/tests/test115.ans
new file mode 100755 (executable)
index 0000000..0e2897e
--- /dev/null
@@ -0,0 +1,40 @@
+hello, world0
+hello, world1
+hello, world2
+hello, world3
+hello, world4
+hello, world5
+hello, world6
+hello, world7
+hello, world8
+hello, world9
+hello, world0, 0
+hello, world1, 1
+hello, world2, 2
+hello, world3, 3
+hello, world4, 4
+hello, world5, 5
+hello, world6, 6
+hello, world7, 7
+hello, world8, 8
+hello, world9, 9
+hello, world0, 0
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world1, 1
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world2, 2
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world3, 3
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world4, 4
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world5, 5
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world6, 6
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world7, 7
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world8, 8
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world9, 9
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/libs/libtpl-1.5/tests/test115.c b/libs/libtpl-1.5/tests/test115.c
new file mode 100755 (executable)
index 0000000..010d6c0
--- /dev/null
@@ -0,0 +1,119 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tpl.h"
+
+#define COUNT 10
+#define BUF_SIZE 256
+const char *filename = "/tmp/test115.tpl";
+
+typedef struct {
+   char* s;
+} s1_t;
+
+
+typedef struct {
+   char* s;
+   int i;
+} s2_t;
+
+
+typedef struct {
+   char c[BUF_SIZE];
+   char* s;
+   int i;
+} s3_t;
+
+
+const char hw[]="hello, world!";
+
+int main ()
+{
+   tpl_node* tn;
+   s1_t* s1, *S1;
+   s2_t* s2, *S2;
+   s3_t* s3, *S3;
+   int i;
+
+   /* case 1: */
+   s1 = (s1_t*)calloc (sizeof (s1_t), COUNT);
+   for(i=0; i < COUNT; i++) {
+     s1[i].s = malloc(sizeof(hw));
+     memcpy(s1[i].s, hw, sizeof(hw));
+     s1[i].s[sizeof(hw)-2]='0'+i;
+   }
+   tn = tpl_map ("S(s)#", s1, COUNT);
+   tpl_pack (tn, 0);
+   tpl_dump (tn, TPL_FILE, filename);
+   tpl_free (tn);
+   for(i=0; i < COUNT; i++) free(s1[i].s);
+
+   S1 = (s1_t*)calloc (sizeof (s1_t), COUNT);
+   memset(S1, 0xff, sizeof(s1_t)*COUNT);
+   tn = tpl_map ("S(s)#", S1, COUNT);
+   tpl_load (tn, TPL_FILE, filename);
+   tpl_unpack (tn, 0);
+   tpl_free (tn);
+
+   for(i=0; i<COUNT; i++) {
+     printf("%s\n", S1[i].s);
+   }
+
+
+   /* case 2: */
+   s2 = (s2_t*)calloc (sizeof (s2_t), COUNT);
+   for(i=0; i < COUNT; i++) {
+     s2[i].s = malloc(sizeof(hw));
+     memcpy(s2[i].s, hw, sizeof(hw));
+     s2[i].s[sizeof(hw)-2]='0'+i;
+     s2[i].i=i;
+   }
+   tn = tpl_map ("S(si)#", s2, COUNT);
+   tpl_pack (tn, 0);
+   tpl_dump (tn, TPL_FILE, filename);
+   tpl_free (tn);
+   for(i=0; i < COUNT; i++) free(s2[i].s);
+
+   S2 = (s2_t*)calloc (sizeof (s2_t), COUNT);
+   memset(S2, 0xff, sizeof(s2_t)*COUNT);
+   tn = tpl_map ("S(si)#", S2, COUNT);
+   tpl_load (tn, TPL_FILE, filename);
+   tpl_unpack (tn, 0);
+   tpl_free (tn);
+
+   for(i=0; i<COUNT; i++) {
+     printf("%s, %u\n", S2[i].s, S2[i].i);
+   }
+
+
+   /* case 3: */
+   s3 = (s3_t*)calloc (sizeof (s3_t), COUNT);
+   for(i=0; i < COUNT; i++) {
+     memset(s3[i].c, 'a', BUF_SIZE);
+     s3[i].c[BUF_SIZE-1]='\0';
+     s3[i].s = malloc(sizeof(hw));
+     memcpy(s3[i].s, hw, sizeof(hw));
+     s3[i].s[sizeof(hw)-2]='0'+i;
+     s3[i].i=i;
+   }
+   tn = tpl_map ("S(c#si)#", s3, BUF_SIZE, COUNT);
+   tpl_pack (tn, 0);
+   tpl_dump (tn, TPL_FILE, filename);
+   tpl_free (tn);
+
+   S3 = (s3_t*)calloc (sizeof (s3_t), COUNT);
+   memset(S3, 0xff, sizeof(s3_t)*COUNT);
+   tn = tpl_map ("S(c#si)#", S3, BUF_SIZE, COUNT);
+   tpl_load (tn, TPL_FILE, filename);
+   tpl_unpack (tn, 0);
+   tpl_free (tn);
+
+   for(i=0; i<COUNT; i++) {
+     printf("%s, %u\n", S3[i].s, S3[i].i);
+     printf("%s\n", S3[i].c);
+   }
+
+   return 0;
+}
+
diff --git a/libs/libtpl-1.5/tests/test115.out b/libs/libtpl-1.5/tests/test115.out
new file mode 100644 (file)
index 0000000..0e2897e
--- /dev/null
@@ -0,0 +1,40 @@
+hello, world0
+hello, world1
+hello, world2
+hello, world3
+hello, world4
+hello, world5
+hello, world6
+hello, world7
+hello, world8
+hello, world9
+hello, world0, 0
+hello, world1, 1
+hello, world2, 2
+hello, world3, 3
+hello, world4, 4
+hello, world5, 5
+hello, world6, 6
+hello, world7, 7
+hello, world8, 8
+hello, world9, 9
+hello, world0, 0
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world1, 1
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world2, 2
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world3, 3
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world4, 4
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world5, 5
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world6, 6
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world7, 7
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world8, 8
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+hello, world9, 9
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/libs/libtpl-1.5/tests/test116 b/libs/libtpl-1.5/tests/test116
new file mode 100755 (executable)
index 0000000..52f7622
Binary files /dev/null and b/libs/libtpl-1.5/tests/test116 differ
diff --git a/libs/libtpl-1.5/tests/test116.ans b/libs/libtpl-1.5/tests/test116.ans
new file mode 100755 (executable)
index 0000000..b3a5deb
--- /dev/null
@@ -0,0 +1,4 @@
+1 a
+alpha
+beta
+gamma
diff --git a/libs/libtpl-1.5/tests/test116.c b/libs/libtpl-1.5/tests/test116.c
new file mode 100755 (executable)
index 0000000..35f124b
--- /dev/null
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include "tpl.h"
+
+#define NUM_STRS 3
+
+const char *filename = "/tmp/test116.tpl";
+
+int main() {
+  tpl_node *tn;
+  int i,d=1,D=-1;
+  char c='a', C='0';
+  char *strs[NUM_STRS] = {"alpha", "beta", "gamma"};
+  char *STRS[NUM_STRS] = {"femto", "nano", "centi"};
+
+  tn = tpl_map("cs#i", &c, strs, NUM_STRS, &d);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("cs#i", &C, STRS, NUM_STRS, &D);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  printf("%d %c\n", D, C);
+  for(i=0;i<NUM_STRS;i++) printf("%s\n", STRS[i]);
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test116.out b/libs/libtpl-1.5/tests/test116.out
new file mode 100644 (file)
index 0000000..b3a5deb
--- /dev/null
@@ -0,0 +1,4 @@
+1 a
+alpha
+beta
+gamma
diff --git a/libs/libtpl-1.5/tests/test117 b/libs/libtpl-1.5/tests/test117
new file mode 100755 (executable)
index 0000000..50783e0
Binary files /dev/null and b/libs/libtpl-1.5/tests/test117 differ
diff --git a/libs/libtpl-1.5/tests/test117.ans b/libs/libtpl-1.5/tests/test117.ans
new file mode 100755 (executable)
index 0000000..067731c
--- /dev/null
@@ -0,0 +1,10 @@
+apple
+bpple
+cpple
+apple
+bpple
+cpple
+apple
+bpple
+cpple
+1 a
diff --git a/libs/libtpl-1.5/tests/test117.c b/libs/libtpl-1.5/tests/test117.c
new file mode 100755 (executable)
index 0000000..f3098ae
--- /dev/null
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tpl.h"
+
+#define NUM_STRS 3
+#define NUM_ELMT 3
+#define STR "apple"
+#define SLEN 5
+
+const char *filename = "/tmp/test117.tpl";
+
+int main() {
+  tpl_node *tn;
+  int i,j,d=1,D=-1;
+  char c='a', C='0';
+  char *strs[NUM_STRS];
+  char *STRS[NUM_STRS];
+
+  tn = tpl_map("cA(s#)i", &c, strs, NUM_STRS, &d);
+  for(i=0; i<NUM_ELMT; i++) {  /* pack the same thing this many times*/
+    for(j=0; j<NUM_STRS; j++) {/* each time just tweaking them a bit */
+      strs[j] = malloc( SLEN+1 );
+      memcpy(strs[j], STR, SLEN+1);
+      strs[j][0] = 'a'+j;
+    }
+    tpl_pack(tn,1);
+  }
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("cA(s#)i", &C, STRS, NUM_STRS, &D);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  while(tpl_unpack(tn,1)>0) {
+    for(i=0;i<NUM_STRS;i++) {
+      printf("%s\n", STRS[i]);
+      free(STRS[i]);
+    }
+  }
+  tpl_free(tn);
+
+  printf("%d %c\n", D, C);
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test117.out b/libs/libtpl-1.5/tests/test117.out
new file mode 100644 (file)
index 0000000..067731c
--- /dev/null
@@ -0,0 +1,10 @@
+apple
+bpple
+cpple
+apple
+bpple
+cpple
+apple
+bpple
+cpple
+1 a
diff --git a/libs/libtpl-1.5/tests/test118 b/libs/libtpl-1.5/tests/test118
new file mode 100755 (executable)
index 0000000..49f8e43
Binary files /dev/null and b/libs/libtpl-1.5/tests/test118 differ
diff --git a/libs/libtpl-1.5/tests/test118.ans b/libs/libtpl-1.5/tests/test118.ans
new file mode 100755 (executable)
index 0000000..e604dcd
--- /dev/null
@@ -0,0 +1,5 @@
+format cA(i#)S(cf#)A(ci#)
+num_fxlens 3
+fxlens[0] 10
+fxlens[1] 5
+fxlens[2] 8
diff --git a/libs/libtpl-1.5/tests/test118.c b/libs/libtpl-1.5/tests/test118.c
new file mode 100755 (executable)
index 0000000..ac675de
--- /dev/null
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define ILEN 10
+#define KLEN 8
+#define FLEN 5
+
+struct st {
+    char c;
+    double f[FLEN];
+};
+
+const char *filename = "/tmp/test118.tpl";
+
+int main() {
+    tpl_node *tn;
+    /* some meaningless test data */
+    struct st s = {'z', {0.9, 0.8, 0.7, 0.6, 0.5 }};
+    int j; 
+    int i[ILEN] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+    int k[KLEN] = {100, 200, 300, 400, 500, 600, 700, 800};
+    char a = '&';
+    char b = 'x';
+    const char *fmt;
+    uint32_t num_fxlens, *fxlens;
+
+    tn = tpl_map("cA(i#)S(cf#)A(ci#)", &a, i, ILEN, &s, FLEN, &b, k, KLEN);
+    tpl_pack(tn,0);
+
+    tpl_pack(tn,1);
+    for(j=0; j < ILEN; j++) i[j]--;
+    tpl_pack(tn,1);
+    for(j=0; j < ILEN; j++) i[j]--;
+    tpl_pack(tn,1);
+
+    tpl_pack(tn,2);
+    b++;
+    for(j=0; j < KLEN; j++) k[j] += 50;  
+    tpl_pack(tn,2);
+    b++;
+    for(j=0; j < KLEN; j++) k[j] += 50; 
+    tpl_pack(tn,2);
+
+    tpl_dump(tn,TPL_FILE,filename);
+    tpl_free(tn);
+
+    /* now peek at the fxlens */
+    fmt = tpl_peek(TPL_FILE|TPL_FXLENS, filename, &num_fxlens, &fxlens);
+    printf("format %s\n", fmt);
+    printf("num_fxlens %u\n", num_fxlens);
+    for(j=0; j<num_fxlens; j++) printf("fxlens[%u] %u\n", j, fxlens[j]);
+    if (num_fxlens>0) free(fxlens);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test118.out b/libs/libtpl-1.5/tests/test118.out
new file mode 100644 (file)
index 0000000..e604dcd
--- /dev/null
@@ -0,0 +1,5 @@
+format cA(i#)S(cf#)A(ci#)
+num_fxlens 3
+fxlens[0] 10
+fxlens[1] 5
+fxlens[2] 8
diff --git a/libs/libtpl-1.5/tests/test119 b/libs/libtpl-1.5/tests/test119
new file mode 100755 (executable)
index 0000000..d5b2d9a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test119 differ
diff --git a/libs/libtpl-1.5/tests/test119.ans b/libs/libtpl-1.5/tests/test119.ans
new file mode 100755 (executable)
index 0000000..9a47712
--- /dev/null
@@ -0,0 +1 @@
+size is 1726
diff --git a/libs/libtpl-1.5/tests/test119.c b/libs/libtpl-1.5/tests/test119.c
new file mode 100755 (executable)
index 0000000..f1e65b7
--- /dev/null
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "tpl.h"
+
+const char *filename = "/tmp/test119.tpl";
+
+#define NUM 100
+
+struct st {
+  int i;
+  char c;
+  double f;
+  uint16_t v[2];
+};
+
+
+int main() {
+  struct st s[NUM], d[NUM];
+  tpl_node *tn; 
+  int i;
+  uint32_t sz=0;
+
+  memset(s, 0, sizeof(s)); /* clear s */
+  memset(d, 0, sizeof(d)); /* clear d */
+
+  /* fill s with random stuff */
+  for(i=0; i < NUM; i++) {
+    s[i].i = i; s[i].c='a'+i; s[i].f = 3.14159 * i; s[i].v[0] = NUM*i; s[i].v[1] = NUM+i; 
+  }
+
+  tn = tpl_map("S(icfv#)#", s, 2, NUM);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_GETSIZE,&sz);
+  tpl_free(tn);
+
+  printf("size is %u\n", sz);
+
+  return 0;
+}
+
diff --git a/libs/libtpl-1.5/tests/test119.out b/libs/libtpl-1.5/tests/test119.out
new file mode 100644 (file)
index 0000000..9a47712
--- /dev/null
@@ -0,0 +1 @@
+size is 1726
diff --git a/libs/libtpl-1.5/tests/test12 b/libs/libtpl-1.5/tests/test12
new file mode 100755 (executable)
index 0000000..632091d
Binary files /dev/null and b/libs/libtpl-1.5/tests/test12 differ
diff --git a/libs/libtpl-1.5/tests/test12.ans b/libs/libtpl-1.5/tests/test12.ans
new file mode 100755 (executable)
index 0000000..c8e2333
--- /dev/null
@@ -0,0 +1 @@
+test12.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test12.c b/libs/libtpl-1.5/tests/test12.c
new file mode 100755 (executable)
index 0000000..51c50bc
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test12.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test12.out b/libs/libtpl-1.5/tests/test12.out
new file mode 100644 (file)
index 0000000..c8e2333
--- /dev/null
@@ -0,0 +1 @@
+test12.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test12.tpl b/libs/libtpl-1.5/tests/test12.tpl
new file mode 100755 (executable)
index 0000000..de74a8b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test12.tpl differ
diff --git a/libs/libtpl-1.5/tests/test120 b/libs/libtpl-1.5/tests/test120
new file mode 100755 (executable)
index 0000000..bf27ab7
Binary files /dev/null and b/libs/libtpl-1.5/tests/test120 differ
diff --git a/libs/libtpl-1.5/tests/test120.ans b/libs/libtpl-1.5/tests/test120.ans
new file mode 100755 (executable)
index 0000000..c527a46
--- /dev/null
@@ -0,0 +1,12 @@
+testing undersized output buffer... -1 
+testing sufficient output buffer... 0 
+j is 0
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
diff --git a/libs/libtpl-1.5/tests/test120.c b/libs/libtpl-1.5/tests/test120.c
new file mode 100755 (executable)
index 0000000..440f18a
--- /dev/null
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i,rc,j;
+    char toosmall[10];
+    char buf[60];
+
+    tn = tpl_map("A(i)",&i);
+    for(i=0;i<10;i++) tpl_pack(tn,1);
+    rc=tpl_dump(tn,TPL_MEM|TPL_PREALLOCD,toosmall,sizeof(toosmall));
+    printf("testing undersized output buffer... %d \n", rc);
+    rc=tpl_dump(tn,TPL_MEM|TPL_PREALLOCD,buf,sizeof(buf));
+    printf("testing sufficient output buffer... %d \n", rc);
+    tpl_free(tn);
+
+    tn = tpl_map("A(i)",&j);
+    tpl_load(tn,TPL_MEM|TPL_EXCESS_OK,buf,sizeof(buf)); 
+    while (tpl_unpack(tn,1) > 0) printf("j is %d\n", j);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test120.err b/libs/libtpl-1.5/tests/test120.err
new file mode 100644 (file)
index 0000000..8d6b384
--- /dev/null
@@ -0,0 +1 @@
+tpl_dump: buffer too small, need 57 bytes
diff --git a/libs/libtpl-1.5/tests/test120.out b/libs/libtpl-1.5/tests/test120.out
new file mode 100644 (file)
index 0000000..c527a46
--- /dev/null
@@ -0,0 +1,12 @@
+testing undersized output buffer... -1 
+testing sufficient output buffer... 0 
+j is 0
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
diff --git a/libs/libtpl-1.5/tests/test121 b/libs/libtpl-1.5/tests/test121
new file mode 100755 (executable)
index 0000000..52477cc
Binary files /dev/null and b/libs/libtpl-1.5/tests/test121 differ
diff --git a/libs/libtpl-1.5/tests/test121.ans b/libs/libtpl-1.5/tests/test121.ans
new file mode 100755 (executable)
index 0000000..6c90699
--- /dev/null
@@ -0,0 +1,6 @@
+one
+two
+three
+eins
+zwei
+drei
diff --git a/libs/libtpl-1.5/tests/test121.c b/libs/libtpl-1.5/tests/test121.c
new file mode 100755 (executable)
index 0000000..f5a9585
--- /dev/null
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+const char *filename = "/tmp/test121.tpl";
+int main() {
+  char *labels[2][3] = { {"one", "two", "three"},
+                         {"eins", "zwei", "drei" } };
+  char *olabels[2][3] = { {NULL,NULL,NULL }, {NULL,NULL,NULL}};
+  int i,j;
+
+  tpl_node *tn;
+  tn = tpl_map("s##", labels, 2, 3);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  tn = tpl_map("s##", olabels, 2, 3);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+
+  for(i=0;i<2;i++) {
+    for(j=0;j<3;j++) {
+      printf("%s\n", olabels[i][j]);
+      free(olabels[i][j]);
+    }
+  }
+
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test121.out b/libs/libtpl-1.5/tests/test121.out
new file mode 100644 (file)
index 0000000..6c90699
--- /dev/null
@@ -0,0 +1,6 @@
+one
+two
+three
+eins
+zwei
+drei
diff --git a/libs/libtpl-1.5/tests/test122 b/libs/libtpl-1.5/tests/test122
new file mode 100755 (executable)
index 0000000..362df69
Binary files /dev/null and b/libs/libtpl-1.5/tests/test122 differ
diff --git a/libs/libtpl-1.5/tests/test122.ans b/libs/libtpl-1.5/tests/test122.ans
new file mode 100755 (executable)
index 0000000..e4c3c1b
--- /dev/null
@@ -0,0 +1 @@
+1 abc 3.140000 a 1
diff --git a/libs/libtpl-1.5/tests/test122.c b/libs/libtpl-1.5/tests/test122.c
new file mode 100755 (executable)
index 0000000..9a3d38c
--- /dev/null
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "tpl.h"
+
+const char *filename = "/tmp/test122.tpl";
+
+typedef struct {
+  char c;
+  int i;
+} inner_t;
+
+typedef struct {
+    int i;
+    char c[3];
+    double f;
+    inner_t inner;
+} outer;
+
+int main() {
+    tpl_node *tn;
+    outer ms = {1, {'a','b','c'}, 3.14, {'a',1}};
+    outer os;
+
+    tn = tpl_map( "S(ic#f$(ci))", &ms, 3);
+    tpl_pack( tn, 0 );
+    tpl_dump( tn, TPL_FILE, filename );
+    tpl_free( tn );
+
+    memset(&os, 0, sizeof(outer));
+    tn = tpl_map( "S(ic#f$(ci))", &os, 3);
+    tpl_load( tn, TPL_FILE, filename );
+    tpl_unpack( tn, 0 );
+    tpl_free( tn );
+
+    printf("%d %c%c%c %f %c %d\n", os.i, os.c[0],os.c[1],os.c[2],os.f,
+      os.inner.c, os.inner.i);
+
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test122.out b/libs/libtpl-1.5/tests/test122.out
new file mode 100644 (file)
index 0000000..e4c3c1b
--- /dev/null
@@ -0,0 +1 @@
+1 abc 3.140000 a 1
diff --git a/libs/libtpl-1.5/tests/test123 b/libs/libtpl-1.5/tests/test123
new file mode 100755 (executable)
index 0000000..a4de2c3
Binary files /dev/null and b/libs/libtpl-1.5/tests/test123 differ
diff --git a/libs/libtpl-1.5/tests/test123.ans b/libs/libtpl-1.5/tests/test123.ans
new file mode 100755 (executable)
index 0000000..41e76f1
--- /dev/null
@@ -0,0 +1 @@
+caught error!
diff --git a/libs/libtpl-1.5/tests/test123.c b/libs/libtpl-1.5/tests/test123.c
new file mode 100755 (executable)
index 0000000..7d82530
--- /dev/null
@@ -0,0 +1,33 @@
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "tpl.h"
+
+jmp_buf env;
+extern tpl_hook_t tpl_hook;
+
+int catch_oops(const char *fmt, ...) {
+  va_list ap;
+
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+  longjmp(env,-1);                /* return to setjmp point */
+  return 0; /* not reached */
+}
+
+int main() {
+  int err;
+  tpl_node *tn;
+  tpl_hook.oops = catch_oops;    /* install fatal handler */
+
+  err = setjmp(env); /* on error, control will return here  */
+  if (err) {
+    printf("caught error!\n");
+    return -1;
+  }
+
+  tn = tpl_map("@");              /* generate a fatal error */
+  printf("program ending, without error\n");
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test123.err b/libs/libtpl-1.5/tests/test123.err
new file mode 100644 (file)
index 0000000..6db6f47
--- /dev/null
@@ -0,0 +1 @@
+unsupported option @
diff --git a/libs/libtpl-1.5/tests/test123.out b/libs/libtpl-1.5/tests/test123.out
new file mode 100644 (file)
index 0000000..41e76f1
--- /dev/null
@@ -0,0 +1 @@
+caught error!
diff --git a/libs/libtpl-1.5/tests/test124 b/libs/libtpl-1.5/tests/test124
new file mode 100755 (executable)
index 0000000..cbf269d
Binary files /dev/null and b/libs/libtpl-1.5/tests/test124 differ
diff --git a/libs/libtpl-1.5/tests/test124.ans b/libs/libtpl-1.5/tests/test124.ans
new file mode 100755 (executable)
index 0000000..121d371
--- /dev/null
@@ -0,0 +1,4 @@
+mapped
+freed
+abcdefghi first
+jklmnopqr second
diff --git a/libs/libtpl-1.5/tests/test124.c b/libs/libtpl-1.5/tests/test124.c
new file mode 100755 (executable)
index 0000000..02020d6
--- /dev/null
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <string.h>
+#include "tpl.h"
+#define LEN 10
+
+const char *filename = "/tmp/test124.tpl";
+
+typedef struct {
+  char name[LEN];
+} test_t;
+int main() {
+  test_t t;
+  char *s;
+  tpl_node *tn;
+
+  tn = tpl_map("A(S(c#)s)", &t, LEN, &s);
+  printf("mapped\n");
+
+  memcpy(t.name,"abcdefghi\0",10);
+  s="first";
+  tpl_pack(tn,1);
+
+  memcpy(t.name,"jklmnopqr\0",10);
+  s="second";
+  tpl_pack(tn,1);
+
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+  printf("freed\n");
+
+  tn = tpl_map("A(S(c#)s)", &t, LEN, &s);
+  tpl_load(tn,TPL_FILE,filename);
+  while(tpl_unpack(tn,1) > 0) {
+      printf("%s %s\n", t.name, s);
+  }
+  tpl_free(tn);
+  return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test124.out b/libs/libtpl-1.5/tests/test124.out
new file mode 100644 (file)
index 0000000..121d371
--- /dev/null
@@ -0,0 +1,4 @@
+mapped
+freed
+abcdefghi first
+jklmnopqr second
diff --git a/libs/libtpl-1.5/tests/test13 b/libs/libtpl-1.5/tests/test13
new file mode 100755 (executable)
index 0000000..4657448
Binary files /dev/null and b/libs/libtpl-1.5/tests/test13 differ
diff --git a/libs/libtpl-1.5/tests/test13.ans b/libs/libtpl-1.5/tests/test13.ans
new file mode 100755 (executable)
index 0000000..7ebe6e2
--- /dev/null
@@ -0,0 +1 @@
+test13.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test13.c b/libs/libtpl-1.5/tests/test13.c
new file mode 100755 (executable)
index 0000000..140afef
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test13.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test13.out b/libs/libtpl-1.5/tests/test13.out
new file mode 100644 (file)
index 0000000..7ebe6e2
--- /dev/null
@@ -0,0 +1 @@
+test13.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test13.tpl b/libs/libtpl-1.5/tests/test13.tpl
new file mode 100755 (executable)
index 0000000..bf10054
Binary files /dev/null and b/libs/libtpl-1.5/tests/test13.tpl differ
diff --git a/libs/libtpl-1.5/tests/test14 b/libs/libtpl-1.5/tests/test14
new file mode 100755 (executable)
index 0000000..35b0421
Binary files /dev/null and b/libs/libtpl-1.5/tests/test14 differ
diff --git a/libs/libtpl-1.5/tests/test14.ans b/libs/libtpl-1.5/tests/test14.ans
new file mode 100755 (executable)
index 0000000..e803c7d
--- /dev/null
@@ -0,0 +1 @@
+test14.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test14.c b/libs/libtpl-1.5/tests/test14.c
new file mode 100755 (executable)
index 0000000..d22f04c
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test14.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test14.out b/libs/libtpl-1.5/tests/test14.out
new file mode 100644 (file)
index 0000000..e803c7d
--- /dev/null
@@ -0,0 +1 @@
+test14.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test14.tpl b/libs/libtpl-1.5/tests/test14.tpl
new file mode 100755 (executable)
index 0000000..8dfd4a5
Binary files /dev/null and b/libs/libtpl-1.5/tests/test14.tpl differ
diff --git a/libs/libtpl-1.5/tests/test15 b/libs/libtpl-1.5/tests/test15
new file mode 100755 (executable)
index 0000000..40c3488
Binary files /dev/null and b/libs/libtpl-1.5/tests/test15 differ
diff --git a/libs/libtpl-1.5/tests/test15.ans b/libs/libtpl-1.5/tests/test15.ans
new file mode 100755 (executable)
index 0000000..f0c2f49
--- /dev/null
@@ -0,0 +1 @@
+test15.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test15.c b/libs/libtpl-1.5/tests/test15.c
new file mode 100755 (executable)
index 0000000..89cf40a
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test15.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test15.out b/libs/libtpl-1.5/tests/test15.out
new file mode 100644 (file)
index 0000000..f0c2f49
--- /dev/null
@@ -0,0 +1 @@
+test15.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test15.tpl b/libs/libtpl-1.5/tests/test15.tpl
new file mode 100755 (executable)
index 0000000..80a8338
Binary files /dev/null and b/libs/libtpl-1.5/tests/test15.tpl differ
diff --git a/libs/libtpl-1.5/tests/test16 b/libs/libtpl-1.5/tests/test16
new file mode 100755 (executable)
index 0000000..180a875
Binary files /dev/null and b/libs/libtpl-1.5/tests/test16 differ
diff --git a/libs/libtpl-1.5/tests/test16.ans b/libs/libtpl-1.5/tests/test16.ans
new file mode 100755 (executable)
index 0000000..db2bed3
--- /dev/null
@@ -0,0 +1 @@
+test16.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test16.c b/libs/libtpl-1.5/tests/test16.c
new file mode 100755 (executable)
index 0000000..400d83f
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test16.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test16.out b/libs/libtpl-1.5/tests/test16.out
new file mode 100644 (file)
index 0000000..db2bed3
--- /dev/null
@@ -0,0 +1 @@
+test16.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test16.tpl b/libs/libtpl-1.5/tests/test16.tpl
new file mode 100755 (executable)
index 0000000..4ef0eaa
Binary files /dev/null and b/libs/libtpl-1.5/tests/test16.tpl differ
diff --git a/libs/libtpl-1.5/tests/test17 b/libs/libtpl-1.5/tests/test17
new file mode 100755 (executable)
index 0000000..403f8e5
Binary files /dev/null and b/libs/libtpl-1.5/tests/test17 differ
diff --git a/libs/libtpl-1.5/tests/test17.ans b/libs/libtpl-1.5/tests/test17.ans
new file mode 100755 (executable)
index 0000000..7519cbf
--- /dev/null
@@ -0,0 +1 @@
+test17.tpl: format signature mismatch
diff --git a/libs/libtpl-1.5/tests/test17.c b/libs/libtpl-1.5/tests/test17.c
new file mode 100755 (executable)
index 0000000..551e382
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(c)",&i);
+    tpl_load(tn,TPL_FILE,"test17.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test17.out b/libs/libtpl-1.5/tests/test17.out
new file mode 100644 (file)
index 0000000..7519cbf
--- /dev/null
@@ -0,0 +1 @@
+test17.tpl: format signature mismatch
diff --git a/libs/libtpl-1.5/tests/test17.tpl b/libs/libtpl-1.5/tests/test17.tpl
new file mode 100755 (executable)
index 0000000..a811f62
Binary files /dev/null and b/libs/libtpl-1.5/tests/test17.tpl differ
diff --git a/libs/libtpl-1.5/tests/test18 b/libs/libtpl-1.5/tests/test18
new file mode 100755 (executable)
index 0000000..d7fcd4a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test18 differ
diff --git a/libs/libtpl-1.5/tests/test18.ans b/libs/libtpl-1.5/tests/test18.ans
new file mode 100755 (executable)
index 0000000..c12a153
--- /dev/null
@@ -0,0 +1,2 @@
+failed to parse A(i
+tpl map failed
diff --git a/libs/libtpl-1.5/tests/test18.c b/libs/libtpl-1.5/tests/test18.c
new file mode 100755 (executable)
index 0000000..3a8f106
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i=-1;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(i",&i);
+    printf("tpl map %s\n", tn ? "succeeded" : "failed");
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test18.out b/libs/libtpl-1.5/tests/test18.out
new file mode 100644 (file)
index 0000000..c12a153
--- /dev/null
@@ -0,0 +1,2 @@
+failed to parse A(i
+tpl map failed
diff --git a/libs/libtpl-1.5/tests/test19 b/libs/libtpl-1.5/tests/test19
new file mode 100755 (executable)
index 0000000..af939cd
Binary files /dev/null and b/libs/libtpl-1.5/tests/test19 differ
diff --git a/libs/libtpl-1.5/tests/test19.ans b/libs/libtpl-1.5/tests/test19.ans
new file mode 100755 (executable)
index 0000000..3cf2a7d
--- /dev/null
@@ -0,0 +1,2 @@
+failed to parse A(i))
+tpl map failed
diff --git a/libs/libtpl-1.5/tests/test19.c b/libs/libtpl-1.5/tests/test19.c
new file mode 100755 (executable)
index 0000000..accac44
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i=-1;
+
+    tpl_hook.oops = printf;
+    
+    tn = tpl_map("A(i))",&i);
+    printf("tpl map %s\n", tn ? "succeeded" : "failed");
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test19.out b/libs/libtpl-1.5/tests/test19.out
new file mode 100644 (file)
index 0000000..3cf2a7d
--- /dev/null
@@ -0,0 +1,2 @@
+failed to parse A(i))
+tpl map failed
diff --git a/libs/libtpl-1.5/tests/test2 b/libs/libtpl-1.5/tests/test2
new file mode 100755 (executable)
index 0000000..d515e4a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test2 differ
diff --git a/libs/libtpl-1.5/tests/test2.ans b/libs/libtpl-1.5/tests/test2.ans
new file mode 100755 (executable)
index 0000000..858b8f6
--- /dev/null
@@ -0,0 +1 @@
+j is 1
diff --git a/libs/libtpl-1.5/tests/test2.c b/libs/libtpl-1.5/tests/test2.c
new file mode 100755 (executable)
index 0000000..18f9026
--- /dev/null
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i,j=-1;
+
+    tn = tpl_map("i",&i);
+    i=1;
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test2.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("i",&j);
+    tpl_load(tn,TPL_FILE,"/tmp/test2.tpl");
+    tpl_unpack(tn,0);
+    printf("j is %d\n", j);
+    tpl_free(tn);
+    return(0);
+    
+}
diff --git a/libs/libtpl-1.5/tests/test2.out b/libs/libtpl-1.5/tests/test2.out
new file mode 100644 (file)
index 0000000..858b8f6
--- /dev/null
@@ -0,0 +1 @@
+j is 1
diff --git a/libs/libtpl-1.5/tests/test20 b/libs/libtpl-1.5/tests/test20
new file mode 100755 (executable)
index 0000000..b591f64
Binary files /dev/null and b/libs/libtpl-1.5/tests/test20 differ
diff --git a/libs/libtpl-1.5/tests/test20.ans b/libs/libtpl-1.5/tests/test20.ans
new file mode 100755 (executable)
index 0000000..56af0c0
--- /dev/null
@@ -0,0 +1,2 @@
+failed to parse iA()
+tpl map failed
diff --git a/libs/libtpl-1.5/tests/test20.c b/libs/libtpl-1.5/tests/test20.c
new file mode 100755 (executable)
index 0000000..25b0ab0
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("iA()",&i);
+    printf("tpl map %s\n", tn ? "succeeded" : "failed");
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test20.out b/libs/libtpl-1.5/tests/test20.out
new file mode 100644 (file)
index 0000000..56af0c0
--- /dev/null
@@ -0,0 +1,2 @@
+failed to parse iA()
+tpl map failed
diff --git a/libs/libtpl-1.5/tests/test21 b/libs/libtpl-1.5/tests/test21
new file mode 100755 (executable)
index 0000000..fa4f6b8
Binary files /dev/null and b/libs/libtpl-1.5/tests/test21 differ
diff --git a/libs/libtpl-1.5/tests/test21.ans b/libs/libtpl-1.5/tests/test21.ans
new file mode 100755 (executable)
index 0000000..c79f83a
--- /dev/null
@@ -0,0 +1,5 @@
+i,j are 0,1
+i,j are 2,3
+i,j are 4,5
+i,j are 6,7
+i,j are 8,9
diff --git a/libs/libtpl-1.5/tests/test21.c b/libs/libtpl-1.5/tests/test21.c
new file mode 100755 (executable)
index 0000000..67a5b57
--- /dev/null
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i,j=-1;
+
+    tn = tpl_map("A(ii)",&i,&j);
+    for(i=0,j=1;i<10;i+=2,j+=2) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FILE,"/tmp/test21.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(ii)",&i,&j);
+    tpl_load(tn,TPL_FILE,"/tmp/test21.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i,j are %d,%d\n", i,j);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test21.out b/libs/libtpl-1.5/tests/test21.out
new file mode 100644 (file)
index 0000000..c79f83a
--- /dev/null
@@ -0,0 +1,5 @@
+i,j are 0,1
+i,j are 2,3
+i,j are 4,5
+i,j are 6,7
+i,j are 8,9
diff --git a/libs/libtpl-1.5/tests/test22 b/libs/libtpl-1.5/tests/test22
new file mode 100755 (executable)
index 0000000..9e9ceeb
Binary files /dev/null and b/libs/libtpl-1.5/tests/test22 differ
diff --git a/libs/libtpl-1.5/tests/test22.ans b/libs/libtpl-1.5/tests/test22.ans
new file mode 100755 (executable)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test22.c b/libs/libtpl-1.5/tests/test22.c
new file mode 100755 (executable)
index 0000000..a69703b
--- /dev/null
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    unsigned i;
+
+    tn = tpl_map("A(u)",&i);
+    for(i=0;i<10;i++) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FILE,"/tmp/test22.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(u)",&i);
+    tpl_load(tn,TPL_FILE,"/tmp/test22.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test22.out b/libs/libtpl-1.5/tests/test22.out
new file mode 100644 (file)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test23 b/libs/libtpl-1.5/tests/test23
new file mode 100755 (executable)
index 0000000..8dea604
Binary files /dev/null and b/libs/libtpl-1.5/tests/test23 differ
diff --git a/libs/libtpl-1.5/tests/test23.ans b/libs/libtpl-1.5/tests/test23.ans
new file mode 100755 (executable)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test23.c b/libs/libtpl-1.5/tests/test23.c
new file mode 100755 (executable)
index 0000000..52193df
--- /dev/null
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include "tpl.h"
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main() {
+    tpl_node *tn;
+    unsigned i;
+    char *file = "/tmp/test23.tpl";
+    int fd;
+
+    tn = tpl_map("A(u)",&i);
+    for(i=0;i<10;i++) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FILE, file);
+    tpl_free(tn);
+
+    if ( (fd=open( file,O_RDONLY)) == -1) {
+        printf("failed to open %s: %s", file, strerror(errno));
+    }
+
+    tn = tpl_map("A(u)",&i);
+    tpl_load(tn, TPL_FD, fd);
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test23.out b/libs/libtpl-1.5/tests/test23.out
new file mode 100644 (file)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test24 b/libs/libtpl-1.5/tests/test24
new file mode 100755 (executable)
index 0000000..a6bbe68
Binary files /dev/null and b/libs/libtpl-1.5/tests/test24 differ
diff --git a/libs/libtpl-1.5/tests/test24.ans b/libs/libtpl-1.5/tests/test24.ans
new file mode 100755 (executable)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test24.c b/libs/libtpl-1.5/tests/test24.c
new file mode 100755 (executable)
index 0000000..6cc5797
--- /dev/null
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main() {
+    tpl_node *tn;
+    unsigned i;
+    char *file = "test24.tpl";
+    int fd;
+
+    if ( (fd=open( file,O_RDONLY)) == -1) {
+        printf("failed to open %s: %s", file, strerror(errno));
+        exit(-1);
+    }
+
+    tn = tpl_map("A(u)",&i);
+    tpl_load(tn, TPL_FD, fd);
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test24.out b/libs/libtpl-1.5/tests/test24.out
new file mode 100644 (file)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test24.tpl b/libs/libtpl-1.5/tests/test24.tpl
new file mode 100755 (executable)
index 0000000..1b03586
Binary files /dev/null and b/libs/libtpl-1.5/tests/test24.tpl differ
diff --git a/libs/libtpl-1.5/tests/test25 b/libs/libtpl-1.5/tests/test25
new file mode 100755 (executable)
index 0000000..daa4c56
Binary files /dev/null and b/libs/libtpl-1.5/tests/test25 differ
diff --git a/libs/libtpl-1.5/tests/test25.ans b/libs/libtpl-1.5/tests/test25.ans
new file mode 100755 (executable)
index 0000000..9383cfb
--- /dev/null
@@ -0,0 +1 @@
+test25.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test25.c b/libs/libtpl-1.5/tests/test25.c
new file mode 100755 (executable)
index 0000000..7c5ffb0
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    unsigned i;
+    char *file = "test25.tpl";
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(u)",&i);
+    if (tpl_load(tn, TPL_FILE, file) < 0 ) {
+        tpl_free(tn);
+        exit(-1);
+    }
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test25.out b/libs/libtpl-1.5/tests/test25.out
new file mode 100644 (file)
index 0000000..9383cfb
--- /dev/null
@@ -0,0 +1 @@
+test25.tpl: not a valid tpl file
diff --git a/libs/libtpl-1.5/tests/test25.tpl b/libs/libtpl-1.5/tests/test25.tpl
new file mode 100755 (executable)
index 0000000..1b03586
Binary files /dev/null and b/libs/libtpl-1.5/tests/test25.tpl differ
diff --git a/libs/libtpl-1.5/tests/test26 b/libs/libtpl-1.5/tests/test26
new file mode 100755 (executable)
index 0000000..9ef5356
Binary files /dev/null and b/libs/libtpl-1.5/tests/test26 differ
diff --git a/libs/libtpl-1.5/tests/test26.ans b/libs/libtpl-1.5/tests/test26.ans
new file mode 100755 (executable)
index 0000000..bf8028a
--- /dev/null
@@ -0,0 +1,2 @@
+3 tpls gathered.
+999045 is their sum.
diff --git a/libs/libtpl-1.5/tests/test26.c b/libs/libtpl-1.5/tests/test26.c
new file mode 100755 (executable)
index 0000000..dc3dc4f
--- /dev/null
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include "tpl.h"
+
+#define DEBUG 0
+
+int num_tpls = 0, sum_tpls = 0;
+
+int tpl_cb(void *tpl, size_t tpllen, void*data) {
+    int i;
+    tpl_node *tn;
+
+    if (DEBUG) printf("obtained tpl of length %d\n", (int)tpllen);
+    tn = tpl_map("A(i)", &i);
+    tpl_load(tn, TPL_MEM, tpl, tpllen);
+    num_tpls++;
+    while (tpl_unpack(tn,1) > 0) sum_tpls += i;
+    tpl_free(tn); 
+    return 0;
+    
+}
+
+int main() {
+    FILE *f1,*f2;
+    int fdflags,fd,fd1,fd2;
+    int selrc, maxfd;
+    tpl_gather_t *gs1=NULL,*gs2=NULL,**gs;
+
+    struct timeval tv;
+    fd_set rset;
+
+    f1 = popen("cat test26_0.tpl;sleep 1; cat test26_1.tpl", "r");
+    fd1 = fileno(f1); 
+    fdflags = fcntl(fd1, F_GETFL, 0);
+    fcntl( fd1, F_SETFL, fdflags | O_NONBLOCK);
+
+    f2 = popen("cat test26_2.tpl;sleep 1; cat test26_3.tpl", "r");
+    fd2 = fileno(f2); 
+    fdflags = fcntl(fd2, F_GETFL, 0);
+    fcntl( fd2, F_SETFL, fdflags | O_NONBLOCK);
+
+    while (1) {
+        FD_ZERO( &rset );
+        if (fd1 >= 0) FD_SET( fd1, &rset );
+        if (fd2 >= 0) FD_SET( fd2, &rset );
+
+        if (fd1 == -1 && fd2 == -1) {
+            printf("%d tpls gathered.\n",num_tpls);
+            printf("%d is their sum.\n",sum_tpls);
+            return(0);
+        }
+
+        maxfd=0;
+        if (fd1>maxfd) maxfd = fd1;
+        if (fd2>maxfd) maxfd = fd2;
+
+        tv.tv_sec = 5;
+        tv.tv_usec = 0;
+
+        selrc = select(maxfd+1, &rset, NULL, NULL, &tv );
+        if (selrc == -1) {
+           perror("select()");
+        } else if (selrc) {
+            for(fd=0;fd<maxfd+1;fd++) {
+                if ( FD_ISSET(fd, &rset) ) {
+                    if (DEBUG) printf("fd %d readable\n", fd);
+                    gs = (fd1 == fd) ? &gs1 : &gs2;
+                    if (tpl_gather(TPL_GATHER_NONBLOCKING,fd,gs,tpl_cb,NULL) <= 0) {
+                        if (fd1 == fd) {pclose(f1); fd1 = -1; }
+                        if (fd2 == fd) {pclose(f2); fd2 = -1; }
+                    } else {
+                        if (DEBUG) printf("tpl_gather >0\n");
+                    }
+                }
+            }
+        } else {
+            if (DEBUG) printf("timeout\n");  
+        }
+    }
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test26.out b/libs/libtpl-1.5/tests/test26.out
new file mode 100644 (file)
index 0000000..bf8028a
--- /dev/null
@@ -0,0 +1,2 @@
+3 tpls gathered.
+999045 is their sum.
diff --git a/libs/libtpl-1.5/tests/test26_0.tpl b/libs/libtpl-1.5/tests/test26_0.tpl
new file mode 100755 (executable)
index 0000000..a811f62
Binary files /dev/null and b/libs/libtpl-1.5/tests/test26_0.tpl differ
diff --git a/libs/libtpl-1.5/tests/test26_1.tpl b/libs/libtpl-1.5/tests/test26_1.tpl
new file mode 100755 (executable)
index 0000000..85ae076
Binary files /dev/null and b/libs/libtpl-1.5/tests/test26_1.tpl differ
diff --git a/libs/libtpl-1.5/tests/test26_2.tpl b/libs/libtpl-1.5/tests/test26_2.tpl
new file mode 100755 (executable)
index 0000000..73e62d3
Binary files /dev/null and b/libs/libtpl-1.5/tests/test26_2.tpl differ
diff --git a/libs/libtpl-1.5/tests/test26_3.tpl b/libs/libtpl-1.5/tests/test26_3.tpl
new file mode 100755 (executable)
index 0000000..bb209fc
Binary files /dev/null and b/libs/libtpl-1.5/tests/test26_3.tpl differ
diff --git a/libs/libtpl-1.5/tests/test27 b/libs/libtpl-1.5/tests/test27
new file mode 100755 (executable)
index 0000000..ec6951b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test27 differ
diff --git a/libs/libtpl-1.5/tests/test27.ans b/libs/libtpl-1.5/tests/test27.ans
new file mode 100755 (executable)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test27.c b/libs/libtpl-1.5/tests/test27.c
new file mode 100755 (executable)
index 0000000..671fa03
--- /dev/null
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main() {
+    tpl_node *tn;
+    unsigned i,perms;
+    char *file = "/tmp/test27.tpl";
+    int fd;
+
+    perms = S_IRUSR|S_IWUSR; 
+    if ( (fd=open( file,O_RDWR|O_CREAT|O_TRUNC,perms)) == -1) {
+        printf("failed to open %s: %s", file, strerror(errno));
+        exit(-1);
+    }
+
+    tn = tpl_map("A(u)",&i);
+    for(i=0;i<10;i++) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FD, fd);
+    tpl_free(tn);
+
+    lseek(fd,0,SEEK_SET);   /* re-position fd to start of file */
+
+    tn = tpl_map("A(u)",&i);
+    tpl_load(tn, TPL_FD, fd);
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test27.out b/libs/libtpl-1.5/tests/test27.out
new file mode 100644 (file)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test28 b/libs/libtpl-1.5/tests/test28
new file mode 100755 (executable)
index 0000000..4ce901a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test28 differ
diff --git a/libs/libtpl-1.5/tests/test28.ans b/libs/libtpl-1.5/tests/test28.ans
new file mode 100755 (executable)
index 0000000..494c321
--- /dev/null
@@ -0,0 +1 @@
+sum is 49995000
diff --git a/libs/libtpl-1.5/tests/test28.c b/libs/libtpl-1.5/tests/test28.c
new file mode 100755 (executable)
index 0000000..ae17789
--- /dev/null
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include "tpl.h"
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main() {
+    tpl_node *tn;
+    unsigned i, sum=0;
+    int fd[2], pid;
+
+    pipe(fd);
+    if ( (pid = fork()) == 0) {   /* child */
+
+        tn = tpl_map("A(u)",&i);
+        tpl_load(tn, TPL_FD, fd[0]);
+        while (tpl_unpack(tn,1) > 0) sum += i;
+        tpl_free(tn);
+        printf("sum is %d\n", sum);
+
+    } else if (pid > 0) {         /* parent */
+
+        tn = tpl_map("A(u)",&i);
+        for(i=0;i<10000;i++) tpl_pack(tn,1);
+        tpl_dump(tn,TPL_FD, fd[1] );
+        tpl_free(tn);
+
+        waitpid(pid,NULL,0);
+
+    } else if (pid == -1) {
+        perror("fork error");
+    }
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test28.out b/libs/libtpl-1.5/tests/test28.out
new file mode 100644 (file)
index 0000000..494c321
--- /dev/null
@@ -0,0 +1 @@
+sum is 49995000
diff --git a/libs/libtpl-1.5/tests/test29 b/libs/libtpl-1.5/tests/test29
new file mode 100755 (executable)
index 0000000..2c6f04a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test29 differ
diff --git a/libs/libtpl-1.5/tests/test29.ans b/libs/libtpl-1.5/tests/test29.ans
new file mode 100755 (executable)
index 0000000..db001dc
--- /dev/null
@@ -0,0 +1,2 @@
+sum is 49995000
+abcdefghijklmnopqrstuvwxyz
diff --git a/libs/libtpl-1.5/tests/test29.c b/libs/libtpl-1.5/tests/test29.c
new file mode 100755 (executable)
index 0000000..5ed6228
--- /dev/null
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include "tpl.h"
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main() {
+    tpl_node *tn;
+    unsigned i, sum=0;
+    int fd[2], pid;
+    char c;
+
+    pipe(fd);
+    if ( (pid = fork()) == 0) {   /* child */
+
+        tn = tpl_map("A(u)",&i);
+        tpl_load(tn, TPL_FD, fd[0]);
+        while (tpl_unpack(tn,1) > 0) sum += i;
+        tpl_free(tn);
+        printf("sum is %d\n", sum);
+
+        tn = tpl_map("A(c)",&c);
+        tpl_load(tn, TPL_FD, fd[0]);
+        while (tpl_unpack(tn,1) > 0) printf("%c",c);
+        tpl_free(tn);
+        printf("\n");
+
+    } else if (pid > 0) {         /* parent */
+
+        tn = tpl_map("A(u)",&i);
+        for(i=0;i<10000;i++) tpl_pack(tn,1);
+        tpl_dump(tn,TPL_FD, fd[1] );
+        tpl_free(tn);
+
+        tn = tpl_map("A(c)",&c);
+        for(c='a';c<='z';c++) tpl_pack(tn,1);
+        tpl_dump(tn,TPL_FD, fd[1] );
+        tpl_free(tn);
+
+        waitpid(pid,NULL,0);
+
+    } else if (pid == -1) {
+        perror("fork error");
+    }
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test29.out b/libs/libtpl-1.5/tests/test29.out
new file mode 100644 (file)
index 0000000..db001dc
--- /dev/null
@@ -0,0 +1,2 @@
+sum is 49995000
+abcdefghijklmnopqrstuvwxyz
diff --git a/libs/libtpl-1.5/tests/test3 b/libs/libtpl-1.5/tests/test3
new file mode 100755 (executable)
index 0000000..baa0e84
Binary files /dev/null and b/libs/libtpl-1.5/tests/test3 differ
diff --git a/libs/libtpl-1.5/tests/test3.ans b/libs/libtpl-1.5/tests/test3.ans
new file mode 100755 (executable)
index 0000000..c35e4ea
--- /dev/null
@@ -0,0 +1,10 @@
+j is 0
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
diff --git a/libs/libtpl-1.5/tests/test3.c b/libs/libtpl-1.5/tests/test3.c
new file mode 100755 (executable)
index 0000000..57f92cc
--- /dev/null
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i,j=-1;
+
+    tn = tpl_map("A(i)",&i);
+    for(i=0;i<10;i++) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FILE,"/tmp/test3.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(i)",&j);
+    tpl_load(tn,TPL_FILE,"/tmp/test3.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("j is %d\n", j);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test3.out b/libs/libtpl-1.5/tests/test3.out
new file mode 100644 (file)
index 0000000..c35e4ea
--- /dev/null
@@ -0,0 +1,10 @@
+j is 0
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
diff --git a/libs/libtpl-1.5/tests/test30 b/libs/libtpl-1.5/tests/test30
new file mode 100755 (executable)
index 0000000..15039ab
Binary files /dev/null and b/libs/libtpl-1.5/tests/test30 differ
diff --git a/libs/libtpl-1.5/tests/test30.ans b/libs/libtpl-1.5/tests/test30.ans
new file mode 100755 (executable)
index 0000000..1115af8
--- /dev/null
@@ -0,0 +1,2 @@
+buffer length: 4
+good
diff --git a/libs/libtpl-1.5/tests/test30.c b/libs/libtpl-1.5/tests/test30.c
new file mode 100755 (executable)
index 0000000..f54f0bb
--- /dev/null
@@ -0,0 +1,40 @@
+#include "tpl.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+int main(int argc, char*argv[]) {
+    tpl_bin bin;
+    tpl_node *tn;
+    int i;
+    char *file = "/tmp/test30.tpl";
+    char str[10];
+
+    strcpy(str,"good egg");
+    bin.addr = str;
+    bin.sz = 4;  /* just going to pack 'good' (no NUL) */
+
+    tn = tpl_map("B", &bin);
+    tpl_pack(tn,0);
+    memset(str,0,10);   /* just to test that buf was copied */
+    tpl_dump(tn,TPL_FILE,file);
+    tpl_free(tn);
+
+    bin.addr = NULL;
+    bin.sz = 0;
+
+    tn = tpl_map("B", &bin);
+    tpl_load(tn,TPL_FILE,file);
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+
+    /* print the buffer char-by-char ; its not a nul-termd string */
+    printf("buffer length: %u\n", bin.sz);
+    for(i=0; i < bin.sz; i++) printf("%c", ((char*)bin.addr)[i]);
+    printf("\n");
+
+    if (bin.sz > 0) 
+        free(bin.addr);  /* malloc'd for us by tpl_unpack, we must free */
+    return(0);
+}
+
diff --git a/libs/libtpl-1.5/tests/test30.out b/libs/libtpl-1.5/tests/test30.out
new file mode 100644 (file)
index 0000000..1115af8
--- /dev/null
@@ -0,0 +1,2 @@
+buffer length: 4
+good
diff --git a/libs/libtpl-1.5/tests/test31 b/libs/libtpl-1.5/tests/test31
new file mode 100755 (executable)
index 0000000..7565901
Binary files /dev/null and b/libs/libtpl-1.5/tests/test31 differ
diff --git a/libs/libtpl-1.5/tests/test31.ans b/libs/libtpl-1.5/tests/test31.ans
new file mode 100755 (executable)
index 0000000..ab23e54
--- /dev/null
@@ -0,0 +1,2 @@
+buffer length: 0
+
diff --git a/libs/libtpl-1.5/tests/test31.c b/libs/libtpl-1.5/tests/test31.c
new file mode 100755 (executable)
index 0000000..ae3c908
--- /dev/null
@@ -0,0 +1,38 @@
+#include "tpl.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(int argc, char*argv[]) {
+    tpl_bin bin;
+    tpl_node *tn;
+    int i;
+    char *file = "/tmp/test31.tpl";
+
+    bin.addr = NULL;
+    bin.sz = 0;  
+
+    tn = tpl_map("B", &bin);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,file);
+    tpl_free(tn);
+
+    /* load these two fields with bogus values to test that tpl_unpack
+     * sets them back to NULL, and 0 respectively.  */
+    bin.addr = file;  
+    bin.sz = 4;      
+
+    tn = tpl_map("B", &bin);
+    tpl_load(tn,TPL_FILE,file);
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+
+    /* print the buffer char-by-char ; its not a nul-termd string */
+    printf("buffer length: %u\n", bin.sz);
+    for(i=0; i < bin.sz; i++) printf("%c", ((char*)bin.addr)[i]);
+    printf("\n");
+
+    if (bin.sz > 0) 
+        free(bin.addr);  /* malloc'd for us by tpl_unpack, we must free */
+    return(0);
+}
+
diff --git a/libs/libtpl-1.5/tests/test31.out b/libs/libtpl-1.5/tests/test31.out
new file mode 100644 (file)
index 0000000..ab23e54
--- /dev/null
@@ -0,0 +1,2 @@
+buffer length: 0
+
diff --git a/libs/libtpl-1.5/tests/test32 b/libs/libtpl-1.5/tests/test32
new file mode 100755 (executable)
index 0000000..91bcd96
Binary files /dev/null and b/libs/libtpl-1.5/tests/test32 differ
diff --git a/libs/libtpl-1.5/tests/test32.ans b/libs/libtpl-1.5/tests/test32.ans
new file mode 100755 (executable)
index 0000000..bda4a86
--- /dev/null
@@ -0,0 +1,10 @@
+buffer length: 4
+good
+buffer length: 4
+ood 
+buffer length: 4
+od e
+buffer length: 4
+d eg
+buffer length: 4
+ egg
diff --git a/libs/libtpl-1.5/tests/test32.c b/libs/libtpl-1.5/tests/test32.c
new file mode 100755 (executable)
index 0000000..4d61461
--- /dev/null
@@ -0,0 +1,44 @@
+#include "tpl.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+int main(int argc, char*argv[]) {
+    tpl_bin bin;
+    tpl_node *tn;
+    int i;
+    char *file = "/tmp/test32.tpl";
+    char str[10];
+
+    strcpy(str,"good egg");
+    bin.addr = str;
+    bin.sz = 4;  /* just going to pack 'good' (no NUL) */
+
+    tn = tpl_map("A(B)", &bin);
+    for(i=0; i < 5; i++) {
+        tpl_pack(tn,1);
+        bin.addr = (char*)(bin.addr) + 1;
+    }
+    memset(str,0,10);   /* just to test that buf was copied */
+    tpl_dump(tn,TPL_FILE,file);
+    tpl_free(tn);
+
+    bin.addr = NULL;
+    bin.sz = 0;
+
+    tn = tpl_map("A(B)", &bin);
+    tpl_load(tn,TPL_FILE,file);
+    while (tpl_unpack(tn,1) > 0) {
+        /* print the buffer char-by-char ; its not a nul-termd string */
+        printf("buffer length: %u\n", bin.sz);
+        for(i=0; i < bin.sz; i++) printf("%c", ((char*)bin.addr)[i]);
+        printf("\n");
+
+        if (bin.sz > 0) 
+            free(bin.addr);  /* malloc'd for us by tpl_unpack, we must free */
+    }
+    tpl_free(tn);
+    return(0);
+
+}
+
diff --git a/libs/libtpl-1.5/tests/test32.out b/libs/libtpl-1.5/tests/test32.out
new file mode 100644 (file)
index 0000000..bda4a86
--- /dev/null
@@ -0,0 +1,10 @@
+buffer length: 4
+good
+buffer length: 4
+ood 
+buffer length: 4
+od e
+buffer length: 4
+d eg
+buffer length: 4
+ egg
diff --git a/libs/libtpl-1.5/tests/test33 b/libs/libtpl-1.5/tests/test33
new file mode 100755 (executable)
index 0000000..f47bbec
Binary files /dev/null and b/libs/libtpl-1.5/tests/test33 differ
diff --git a/libs/libtpl-1.5/tests/test33.ans b/libs/libtpl-1.5/tests/test33.ans
new file mode 100755 (executable)
index 0000000..8805eb3
--- /dev/null
@@ -0,0 +1,2 @@
+sizeof(double) is 8
+y is 1.000000
diff --git a/libs/libtpl-1.5/tests/test33.c b/libs/libtpl-1.5/tests/test33.c
new file mode 100755 (executable)
index 0000000..6018b2a
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    double x,y;
+
+    printf("sizeof(double) is %d\n", (int)sizeof(double));
+
+    tn = tpl_map("f",&x);
+    x=1.0;
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test33.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("f",&y);
+    tpl_load(tn,TPL_FILE,"/tmp/test33.tpl");
+    tpl_unpack(tn,0);
+    printf("y is %.6f\n", y);
+    tpl_free(tn);
+    
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test33.out b/libs/libtpl-1.5/tests/test33.out
new file mode 100644 (file)
index 0000000..8805eb3
--- /dev/null
@@ -0,0 +1,2 @@
+sizeof(double) is 8
+y is 1.000000
diff --git a/libs/libtpl-1.5/tests/test34 b/libs/libtpl-1.5/tests/test34
new file mode 100755 (executable)
index 0000000..59db46b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test34 differ
diff --git a/libs/libtpl-1.5/tests/test34.ans b/libs/libtpl-1.5/tests/test34.ans
new file mode 100755 (executable)
index 0000000..6b28190
--- /dev/null
@@ -0,0 +1,15 @@
+sizeof(double) is 8
+y is 1.000000
+y is 1.666667
+y is 2.333333
+y is 3.000000
+y is 3.666667
+y is 4.333333
+y is 5.000000
+y is 5.666667
+y is 6.333333
+y is 7.000000
+y is 7.666667
+y is 8.333333
+y is 9.000000
+y is 9.666667
diff --git a/libs/libtpl-1.5/tests/test34.c b/libs/libtpl-1.5/tests/test34.c
new file mode 100755 (executable)
index 0000000..a4dd8bf
--- /dev/null
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    double x,y;
+
+    printf("sizeof(double) is %d\n", (int)sizeof(double));
+
+    tn = tpl_map("A(f)",&x);
+    for( x=1.0; x < 10.0; x += 2/3.0) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FILE,"/tmp/test34.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(f)",&y);
+    tpl_load(tn,TPL_FILE,"/tmp/test34.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("y is %.6f\n", y);
+    tpl_free(tn);
+    
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test34.out b/libs/libtpl-1.5/tests/test34.out
new file mode 100644 (file)
index 0000000..6b28190
--- /dev/null
@@ -0,0 +1,15 @@
+sizeof(double) is 8
+y is 1.000000
+y is 1.666667
+y is 2.333333
+y is 3.000000
+y is 3.666667
+y is 4.333333
+y is 5.000000
+y is 5.666667
+y is 6.333333
+y is 7.000000
+y is 7.666667
+y is 8.333333
+y is 9.000000
+y is 9.666667
diff --git a/libs/libtpl-1.5/tests/test35 b/libs/libtpl-1.5/tests/test35
new file mode 100755 (executable)
index 0000000..fb84262
Binary files /dev/null and b/libs/libtpl-1.5/tests/test35 differ
diff --git a/libs/libtpl-1.5/tests/test35.ans b/libs/libtpl-1.5/tests/test35.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test35.c b/libs/libtpl-1.5/tests/test35.c
new file mode 100755 (executable)
index 0000000..65980e7
--- /dev/null
@@ -0,0 +1,16 @@
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    int id;
+    char *name, *names[] = { "joe", "bob", "cary" };
+
+    tn = tpl_map("A(is)", &id, &name);
+
+    for(id=0,name=names[id]; id < 3; name=names[++id])
+        tpl_pack(tn,1);
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test35.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test35.out b/libs/libtpl-1.5/tests/test35.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test36 b/libs/libtpl-1.5/tests/test36
new file mode 100755 (executable)
index 0000000..f406445
Binary files /dev/null and b/libs/libtpl-1.5/tests/test36 differ
diff --git a/libs/libtpl-1.5/tests/test36.ans b/libs/libtpl-1.5/tests/test36.ans
new file mode 100755 (executable)
index 0000000..0b21bfe
--- /dev/null
@@ -0,0 +1,3 @@
+id 0, user joe
+id 1, user bob
+id 2, user cary
diff --git a/libs/libtpl-1.5/tests/test36.c b/libs/libtpl-1.5/tests/test36.c
new file mode 100755 (executable)
index 0000000..5e4867b
--- /dev/null
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    int id;
+    char *name;
+
+    tn = tpl_map("A(is)", &id, &name);
+    tpl_load(tn, TPL_FILE, "/tmp/test35.tpl");
+
+    while ( tpl_unpack(tn,1) > 0 ) {
+        printf("id %d, user %s\n", id, name);
+        free(name);
+    }
+
+    tpl_free(tn);
+    return(0);
+}
+
+
diff --git a/libs/libtpl-1.5/tests/test36.out b/libs/libtpl-1.5/tests/test36.out
new file mode 100644 (file)
index 0000000..0b21bfe
--- /dev/null
@@ -0,0 +1,3 @@
+id 0, user joe
+id 1, user bob
+id 2, user cary
diff --git a/libs/libtpl-1.5/tests/test37 b/libs/libtpl-1.5/tests/test37
new file mode 100755 (executable)
index 0000000..b68ae4a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test37 differ
diff --git a/libs/libtpl-1.5/tests/test37.ans b/libs/libtpl-1.5/tests/test37.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test37.c b/libs/libtpl-1.5/tests/test37.c
new file mode 100755 (executable)
index 0000000..6e619a6
--- /dev/null
@@ -0,0 +1,20 @@
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i,j;
+
+    tn = tpl_map("A(A(i))",&j);
+
+    for(i=2;i<4;i++) {
+
+        for(j=i; j < 10*i; j *= i) {
+            tpl_pack(tn,2);
+        }
+        tpl_pack(tn,1);
+    }
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test37.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test37.out b/libs/libtpl-1.5/tests/test37.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test38 b/libs/libtpl-1.5/tests/test38
new file mode 100755 (executable)
index 0000000..347f3b3
Binary files /dev/null and b/libs/libtpl-1.5/tests/test38 differ
diff --git a/libs/libtpl-1.5/tests/test38.ans b/libs/libtpl-1.5/tests/test38.ans
new file mode 100755 (executable)
index 0000000..157e8cf
--- /dev/null
@@ -0,0 +1,9 @@
+unpacking index 1:
+   unpacking index 2: j is 2
+   unpacking index 2: j is 4
+   unpacking index 2: j is 8
+   unpacking index 2: j is 16
+unpacking index 1:
+   unpacking index 2: j is 3
+   unpacking index 2: j is 9
+   unpacking index 2: j is 27
diff --git a/libs/libtpl-1.5/tests/test38.c b/libs/libtpl-1.5/tests/test38.c
new file mode 100755 (executable)
index 0000000..fd8fc75
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int j;
+
+    tn = tpl_map("A(A(i))",&j);
+    tpl_load(tn,TPL_FILE, "/tmp/test37.tpl");
+
+    while (tpl_unpack(tn,1) > 0) {
+        printf("unpacking index 1:\n");
+        while (tpl_unpack(tn,2) > 0) {
+            printf("   unpacking index 2: j is %d\n", j);
+        }
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test38.out b/libs/libtpl-1.5/tests/test38.out
new file mode 100644 (file)
index 0000000..157e8cf
--- /dev/null
@@ -0,0 +1,9 @@
+unpacking index 1:
+   unpacking index 2: j is 2
+   unpacking index 2: j is 4
+   unpacking index 2: j is 8
+   unpacking index 2: j is 16
+unpacking index 1:
+   unpacking index 2: j is 3
+   unpacking index 2: j is 9
+   unpacking index 2: j is 27
diff --git a/libs/libtpl-1.5/tests/test39 b/libs/libtpl-1.5/tests/test39
new file mode 100755 (executable)
index 0000000..bac2966
Binary files /dev/null and b/libs/libtpl-1.5/tests/test39 differ
diff --git a/libs/libtpl-1.5/tests/test39.ans b/libs/libtpl-1.5/tests/test39.ans
new file mode 100755 (executable)
index 0000000..b2035d8
--- /dev/null
@@ -0,0 +1,2 @@
+test39.tpl: not a valid tpl file
+load failed (rc=-1)
diff --git a/libs/libtpl-1.5/tests/test39.c b/libs/libtpl-1.5/tests/test39.c
new file mode 100755 (executable)
index 0000000..cb892dc
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "tpl.h"
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i, rc;
+
+    tpl_hook.oops = printf;
+
+    tn = tpl_map("A(i)",&i);
+    rc = tpl_load(tn,TPL_FILE,"test39.tpl");
+    printf("load %s (rc=%d)\n", (rc >= 0 ? "ok" : "failed"), rc);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test39.out b/libs/libtpl-1.5/tests/test39.out
new file mode 100644 (file)
index 0000000..b2035d8
--- /dev/null
@@ -0,0 +1,2 @@
+test39.tpl: not a valid tpl file
+load failed (rc=-1)
diff --git a/libs/libtpl-1.5/tests/test39.tpl b/libs/libtpl-1.5/tests/test39.tpl
new file mode 100755 (executable)
index 0000000..37d246c
Binary files /dev/null and b/libs/libtpl-1.5/tests/test39.tpl differ
diff --git a/libs/libtpl-1.5/tests/test4 b/libs/libtpl-1.5/tests/test4
new file mode 100755 (executable)
index 0000000..1699276
Binary files /dev/null and b/libs/libtpl-1.5/tests/test4 differ
diff --git a/libs/libtpl-1.5/tests/test4.ans b/libs/libtpl-1.5/tests/test4.ans
new file mode 100755 (executable)
index 0000000..c35e4ea
--- /dev/null
@@ -0,0 +1,10 @@
+j is 0
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
diff --git a/libs/libtpl-1.5/tests/test4.c b/libs/libtpl-1.5/tests/test4.c
new file mode 100755 (executable)
index 0000000..9972d13
--- /dev/null
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i,j=-1;
+    void *addr;
+    int sz;
+
+    tn = tpl_map("A(i)",&i);
+    for(i=0;i<10;i++) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_MEM,&addr,&sz);
+    tpl_free(tn);
+
+    tn = tpl_map("A(i)",&j);
+    tpl_load(tn,TPL_MEM,addr,sz);
+    while (tpl_unpack(tn,1) > 0) printf("j is %d\n", j);
+    tpl_free(tn);
+    free(addr);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test4.out b/libs/libtpl-1.5/tests/test4.out
new file mode 100644 (file)
index 0000000..c35e4ea
--- /dev/null
@@ -0,0 +1,10 @@
+j is 0
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
diff --git a/libs/libtpl-1.5/tests/test40 b/libs/libtpl-1.5/tests/test40
new file mode 100755 (executable)
index 0000000..62dcb1a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test40 differ
diff --git a/libs/libtpl-1.5/tests/test40.ans b/libs/libtpl-1.5/tests/test40.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test40.c b/libs/libtpl-1.5/tests/test40.c
new file mode 100755 (executable)
index 0000000..4c0992b
--- /dev/null
@@ -0,0 +1,18 @@
+#include "tpl.h"
+
+int main() {
+    char c;
+    tpl_node *tn;
+
+    tn = tpl_map("A(A(c))", &c);
+
+    for(c='a'; c<'c'; c++) tpl_pack(tn,2);
+    tpl_pack(tn, 1);
+
+    for(c='1'; c<'4'; c++) tpl_pack(tn,2);
+    tpl_pack(tn, 1);
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test40.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test40.out b/libs/libtpl-1.5/tests/test40.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test41 b/libs/libtpl-1.5/tests/test41
new file mode 100755 (executable)
index 0000000..7613162
Binary files /dev/null and b/libs/libtpl-1.5/tests/test41 differ
diff --git a/libs/libtpl-1.5/tests/test41.ans b/libs/libtpl-1.5/tests/test41.ans
new file mode 100755 (executable)
index 0000000..5298671
--- /dev/null
@@ -0,0 +1,2 @@
+a b 
+1 2 3 
diff --git a/libs/libtpl-1.5/tests/test41.c b/libs/libtpl-1.5/tests/test41.c
new file mode 100755 (executable)
index 0000000..c5093f0
--- /dev/null
@@ -0,0 +1,18 @@
+#include "tpl.h"
+#include <stdio.h>
+
+int main() {
+    char c;
+    tpl_node *tn;
+
+    tn = tpl_map("A(A(c))", &c);
+
+    tpl_load(tn, TPL_FILE, "/tmp/test40.tpl");
+    while (tpl_unpack(tn,1) > 0) {
+        while (tpl_unpack(tn,2) > 0) printf("%c ",c);
+        printf("\n");
+    }
+    tpl_free(tn);
+    return(0);
+}
+
diff --git a/libs/libtpl-1.5/tests/test41.out b/libs/libtpl-1.5/tests/test41.out
new file mode 100644 (file)
index 0000000..5298671
--- /dev/null
@@ -0,0 +1,2 @@
+a b 
+1 2 3 
diff --git a/libs/libtpl-1.5/tests/test42 b/libs/libtpl-1.5/tests/test42
new file mode 100755 (executable)
index 0000000..043f4fd
Binary files /dev/null and b/libs/libtpl-1.5/tests/test42 differ
diff --git a/libs/libtpl-1.5/tests/test42.ans b/libs/libtpl-1.5/tests/test42.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test42.c b/libs/libtpl-1.5/tests/test42.c
new file mode 100755 (executable)
index 0000000..0f330e8
--- /dev/null
@@ -0,0 +1,16 @@
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    char id;
+    char *name, *names[] = { "joe", "bob", "cary" };
+
+    tn = tpl_map("A(cs)", &id, &name);
+
+    for(id=0,name=names[(int)id]; id < 3; name=names[(int)++id])
+        tpl_pack(tn,1);
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test42.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test42.out b/libs/libtpl-1.5/tests/test42.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test43 b/libs/libtpl-1.5/tests/test43
new file mode 100755 (executable)
index 0000000..e432f40
Binary files /dev/null and b/libs/libtpl-1.5/tests/test43 differ
diff --git a/libs/libtpl-1.5/tests/test43.ans b/libs/libtpl-1.5/tests/test43.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test43.c b/libs/libtpl-1.5/tests/test43.c
new file mode 100755 (executable)
index 0000000..ad0162e
--- /dev/null
@@ -0,0 +1,20 @@
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    char id;
+    tpl_bin bin;
+
+    char *junk = "0123456789";
+    bin.sz = 10;
+    bin.addr = junk;
+
+    tn = tpl_map("A(cB)", &id, &bin);
+
+    for(id=0; id < 3; ++id) 
+        tpl_pack(tn,1);  /* pack same bin buffer, doesn't matter */
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test43.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test43.out b/libs/libtpl-1.5/tests/test43.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test44 b/libs/libtpl-1.5/tests/test44
new file mode 100755 (executable)
index 0000000..b37213b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test44 differ
diff --git a/libs/libtpl-1.5/tests/test44.ans b/libs/libtpl-1.5/tests/test44.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test44.c b/libs/libtpl-1.5/tests/test44.c
new file mode 100755 (executable)
index 0000000..cc25744
--- /dev/null
@@ -0,0 +1,23 @@
+#include "tpl.h"
+
+int main(int argc, char *argv[]) {
+    tpl_node *tn;
+    char id,j;
+    tpl_bin bin;
+
+    char *junk = "0123456789";
+    bin.sz = 10;
+    bin.addr = junk;
+
+    tn = tpl_map("A(cA(B))", &id, &bin);
+
+    for(id=0; id < 3; ++id) {
+        for(j=0;j<2;j++) 
+            tpl_pack(tn,2); /* pack same bin buffer, doesn't matter */
+        tpl_pack(tn,1);  
+    }
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test44.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test44.out b/libs/libtpl-1.5/tests/test44.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test45 b/libs/libtpl-1.5/tests/test45
new file mode 100755 (executable)
index 0000000..fecd446
Binary files /dev/null and b/libs/libtpl-1.5/tests/test45 differ
diff --git a/libs/libtpl-1.5/tests/test45.ans b/libs/libtpl-1.5/tests/test45.ans
new file mode 100755 (executable)
index 0000000..462cb89
--- /dev/null
@@ -0,0 +1,2 @@
+x is 0.500000
+y is 0.500000
diff --git a/libs/libtpl-1.5/tests/test45.c b/libs/libtpl-1.5/tests/test45.c
new file mode 100755 (executable)
index 0000000..ca0fc59
--- /dev/null
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    double x=0.5,y=0.0;
+
+    tn = tpl_map("f",&x);
+    tpl_pack(tn,0);
+    printf("x is %f\n", x);
+    tpl_dump(tn,TPL_FILE,"/tmp/test45.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("f",&y);
+    tpl_load(tn,TPL_FILE,"/tmp/test45.tpl");
+    tpl_unpack(tn,0);
+    printf("y is %f\n", y);
+    tpl_free(tn);
+    return(0);
+    
+}
diff --git a/libs/libtpl-1.5/tests/test45.out b/libs/libtpl-1.5/tests/test45.out
new file mode 100644 (file)
index 0000000..462cb89
--- /dev/null
@@ -0,0 +1,2 @@
+x is 0.500000
+y is 0.500000
diff --git a/libs/libtpl-1.5/tests/test46 b/libs/libtpl-1.5/tests/test46
new file mode 100755 (executable)
index 0000000..4d22b71
Binary files /dev/null and b/libs/libtpl-1.5/tests/test46 differ
diff --git a/libs/libtpl-1.5/tests/test46.ans b/libs/libtpl-1.5/tests/test46.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test46.c b/libs/libtpl-1.5/tests/test46.c
new file mode 100755 (executable)
index 0000000..e497754
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    double x;
+
+    tn = tpl_map("A(f)",&x);
+    for(x=0.0;x<1.0;x+=0.2) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FILE,"/tmp/test46.tpl");
+    tpl_free(tn);
+
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test46.out b/libs/libtpl-1.5/tests/test46.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test47 b/libs/libtpl-1.5/tests/test47
new file mode 100755 (executable)
index 0000000..eb682ed
Binary files /dev/null and b/libs/libtpl-1.5/tests/test47 differ
diff --git a/libs/libtpl-1.5/tests/test47.ans b/libs/libtpl-1.5/tests/test47.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test47.c b/libs/libtpl-1.5/tests/test47.c
new file mode 100755 (executable)
index 0000000..62cc619
--- /dev/null
@@ -0,0 +1,14 @@
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map( "A(i)", &i );
+    for( i=0; i<10; i++ ) {
+        tpl_pack( tn, 1 );  
+    }
+    tpl_dump( tn, TPL_FILE, "/tmp/test47.tpl" );
+    tpl_free( tn );
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test47.out b/libs/libtpl-1.5/tests/test47.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test48 b/libs/libtpl-1.5/tests/test48
new file mode 100755 (executable)
index 0000000..1fb859d
Binary files /dev/null and b/libs/libtpl-1.5/tests/test48 differ
diff --git a/libs/libtpl-1.5/tests/test48.ans b/libs/libtpl-1.5/tests/test48.ans
new file mode 100755 (executable)
index 0000000..a4a2f8e
--- /dev/null
@@ -0,0 +1 @@
+0 1 2 3 4 5 6 7 8 9 
\ No newline at end of file
diff --git a/libs/libtpl-1.5/tests/test48.c b/libs/libtpl-1.5/tests/test48.c
new file mode 100755 (executable)
index 0000000..3cf52f7
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map( "A(i)", &i );
+    tpl_load( tn, TPL_FILE, "/tmp/test47.tpl" );
+    while (tpl_unpack( tn, 1 ) > 0) {
+        printf("%d ", i);
+    }
+    tpl_free( tn );
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test48.out b/libs/libtpl-1.5/tests/test48.out
new file mode 100644 (file)
index 0000000..a4a2f8e
--- /dev/null
@@ -0,0 +1 @@
+0 1 2 3 4 5 6 7 8 9 
\ No newline at end of file
diff --git a/libs/libtpl-1.5/tests/test49 b/libs/libtpl-1.5/tests/test49
new file mode 100755 (executable)
index 0000000..3c03a59
Binary files /dev/null and b/libs/libtpl-1.5/tests/test49 differ
diff --git a/libs/libtpl-1.5/tests/test49.ans b/libs/libtpl-1.5/tests/test49.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test49.c b/libs/libtpl-1.5/tests/test49.c
new file mode 100755 (executable)
index 0000000..9e7f8f2
--- /dev/null
@@ -0,0 +1,18 @@
+    #include "tpl.h"
+
+    int main() {
+        tpl_node *tn;
+        char *s;
+
+        tn = tpl_map( "A(s)", &s );
+
+        s = "bob";
+        tpl_pack(tn, 1);
+
+        s = "betty";
+        tpl_pack(tn, 1);
+
+        tpl_dump(tn, TPL_FILE, "/tmp/test49.tpl");
+        tpl_free(tn);
+        return(0);
+    }
diff --git a/libs/libtpl-1.5/tests/test49.out b/libs/libtpl-1.5/tests/test49.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test5 b/libs/libtpl-1.5/tests/test5
new file mode 100755 (executable)
index 0000000..e28ecef
Binary files /dev/null and b/libs/libtpl-1.5/tests/test5 differ
diff --git a/libs/libtpl-1.5/tests/test5.ans b/libs/libtpl-1.5/tests/test5.ans
new file mode 100755 (executable)
index 0000000..54164a9
--- /dev/null
@@ -0,0 +1,100 @@
+j is 0
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 15
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 15
+j is 16
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 15
+j is 16
+j is 17
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 15
+j is 16
+j is 17
+j is 18
diff --git a/libs/libtpl-1.5/tests/test5.c b/libs/libtpl-1.5/tests/test5.c
new file mode 100755 (executable)
index 0000000..1594fb7
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int o,i,j=-1;
+    void *addr;
+    int sz;
+
+    tn = tpl_map("A(A(i))",&i);
+    for(o=0;o<10;o++) {
+        for(i=o; i < o+10; i++) tpl_pack(tn,2);
+        tpl_pack(tn,1);
+    }
+    tpl_dump(tn,TPL_MEM,&addr,&sz);
+    tpl_free(tn);
+
+    tn = tpl_map("A(A(i))",&j);
+    tpl_load(tn,TPL_MEM,addr,sz);
+    while (tpl_unpack(tn,1) > 0) {
+        while (tpl_unpack(tn,2) > 0) printf("j is %d\n", j);
+    }
+    tpl_free(tn);
+    free(addr);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test5.out b/libs/libtpl-1.5/tests/test5.out
new file mode 100644 (file)
index 0000000..54164a9
--- /dev/null
@@ -0,0 +1,100 @@
+j is 0
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 1
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 2
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 3
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 4
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 5
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 6
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 15
+j is 7
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 15
+j is 16
+j is 8
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 15
+j is 16
+j is 17
+j is 9
+j is 10
+j is 11
+j is 12
+j is 13
+j is 14
+j is 15
+j is 16
+j is 17
+j is 18
diff --git a/libs/libtpl-1.5/tests/test50 b/libs/libtpl-1.5/tests/test50
new file mode 100755 (executable)
index 0000000..aee87af
Binary files /dev/null and b/libs/libtpl-1.5/tests/test50 differ
diff --git a/libs/libtpl-1.5/tests/test50.ans b/libs/libtpl-1.5/tests/test50.ans
new file mode 100755 (executable)
index 0000000..556f45c
--- /dev/null
@@ -0,0 +1,2 @@
+bob
+betty
diff --git a/libs/libtpl-1.5/tests/test50.c b/libs/libtpl-1.5/tests/test50.c
new file mode 100755 (executable)
index 0000000..d7f9d68
--- /dev/null
@@ -0,0 +1,19 @@
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include "tpl.h"
+
+    int main() {
+        tpl_node *tn;
+        char *s;
+
+        tn = tpl_map( "A(s)", &s );
+        tpl_load( tn, TPL_FILE, "/tmp/test49.tpl" );
+
+        while (tpl_unpack( tn, 1 ) > 0) {
+            printf("%s\n", s);
+            free(s);  /* important! */
+        }
+
+        tpl_free(tn);
+        return(0);
+    }
diff --git a/libs/libtpl-1.5/tests/test50.out b/libs/libtpl-1.5/tests/test50.out
new file mode 100644 (file)
index 0000000..556f45c
--- /dev/null
@@ -0,0 +1,2 @@
+bob
+betty
diff --git a/libs/libtpl-1.5/tests/test51 b/libs/libtpl-1.5/tests/test51
new file mode 100755 (executable)
index 0000000..3a06d15
Binary files /dev/null and b/libs/libtpl-1.5/tests/test51 differ
diff --git a/libs/libtpl-1.5/tests/test51.ans b/libs/libtpl-1.5/tests/test51.ans
new file mode 100755 (executable)
index 0000000..bb58756
--- /dev/null
@@ -0,0 +1 @@
+num_tpls: 4, sum: 180
diff --git a/libs/libtpl-1.5/tests/test51.c b/libs/libtpl-1.5/tests/test51.c
new file mode 100755 (executable)
index 0000000..49834d7
--- /dev/null
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "tpl.h"
+
+#define DEBUG 0
+#define FILE_BUFLEN 500
+
+int num_tpls = 0, sum_tpls = 0;
+
+int tpl_cb(void *tpl, size_t tpllen, void*data) {
+    int i;
+    tpl_node *tn;
+
+    if (DEBUG) printf("obtained tpl of length %d\n", (int)tpllen);
+    tn = tpl_map("A(i)", &i);
+    tpl_load(tn, TPL_MEM, tpl, tpllen);
+    num_tpls++;
+    while (tpl_unpack(tn,1) > 0) sum_tpls += i;
+    tpl_free(tn); 
+    return 0;
+    
+}
+
+int main(int argc, char *argv[]) {
+    char *files[] = {"test51_0.tpl", "test51_1.tpl", "test51_2.tpl", "test51_3.tpl","test51_4.tpl", NULL};
+    char **f;
+    char buf[FILE_BUFLEN];
+    int rc,fd;
+    tpl_gather_t *gs=NULL;
+
+    for (f = files; *f; f++) {
+        if (DEBUG) printf("file is %s\n", *f);
+        if ( ( fd = open(*f, O_RDONLY) ) == -1) {
+            printf("error - can't open %s: %s\n", *f, strerror(errno));
+            exit(-1);
+        }
+        rc = read(fd,&buf,FILE_BUFLEN);  /* read whole file (no points for style) */
+        if (rc == -1) {
+            printf("error - can't read %s: %s\n", *f, strerror(errno));
+            exit(-1);
+        }
+        if (tpl_gather(TPL_GATHER_MEM,buf, rc, &gs, tpl_cb, NULL) <= 0) {
+            printf("tpl_gather_mem returned <= 0, exiting\n");
+            exit(-1);
+        }
+        close(fd);
+    }
+    printf("num_tpls: %d, sum: %d\n", num_tpls, sum_tpls);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test51.out b/libs/libtpl-1.5/tests/test51.out
new file mode 100644 (file)
index 0000000..bb58756
--- /dev/null
@@ -0,0 +1 @@
+num_tpls: 4, sum: 180
diff --git a/libs/libtpl-1.5/tests/test51_0.tpl b/libs/libtpl-1.5/tests/test51_0.tpl
new file mode 100755 (executable)
index 0000000..a811f62
Binary files /dev/null and b/libs/libtpl-1.5/tests/test51_0.tpl differ
diff --git a/libs/libtpl-1.5/tests/test51_1.tpl b/libs/libtpl-1.5/tests/test51_1.tpl
new file mode 100755 (executable)
index 0000000..b056e6b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test51_1.tpl differ
diff --git a/libs/libtpl-1.5/tests/test51_2.tpl b/libs/libtpl-1.5/tests/test51_2.tpl
new file mode 100755 (executable)
index 0000000..328940b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test51_2.tpl differ
diff --git a/libs/libtpl-1.5/tests/test51_3.tpl b/libs/libtpl-1.5/tests/test51_3.tpl
new file mode 100755 (executable)
index 0000000..bb74463
Binary files /dev/null and b/libs/libtpl-1.5/tests/test51_3.tpl differ
diff --git a/libs/libtpl-1.5/tests/test51_4.tpl b/libs/libtpl-1.5/tests/test51_4.tpl
new file mode 100755 (executable)
index 0000000..0219500
Binary files /dev/null and b/libs/libtpl-1.5/tests/test51_4.tpl differ
diff --git a/libs/libtpl-1.5/tests/test52 b/libs/libtpl-1.5/tests/test52
new file mode 100755 (executable)
index 0000000..532c908
Binary files /dev/null and b/libs/libtpl-1.5/tests/test52 differ
diff --git a/libs/libtpl-1.5/tests/test52.ans b/libs/libtpl-1.5/tests/test52.ans
new file mode 100755 (executable)
index 0000000..cc17582
--- /dev/null
@@ -0,0 +1,2 @@
+----------
+--> j is 1
diff --git a/libs/libtpl-1.5/tests/test52.c b/libs/libtpl-1.5/tests/test52.c
new file mode 100755 (executable)
index 0000000..364ac3a
--- /dev/null
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int j;
+
+    tn = tpl_map("A(A(i))",&j);
+
+    j=1;
+    tpl_pack(tn,2);
+    tpl_pack(tn,1);
+    j=2;
+    tpl_pack(tn,2);
+    /* omit packing parent */
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test52.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(A(i))",&j);
+    tpl_load(tn, TPL_FILE, "/tmp/test52.tpl");
+    while(tpl_unpack(tn,1) > 0) {
+        printf("----------\n");
+        while(tpl_unpack(tn,2) > 0) {
+            printf("--> j is %d\n", j);
+        }
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test52.out b/libs/libtpl-1.5/tests/test52.out
new file mode 100644 (file)
index 0000000..cc17582
--- /dev/null
@@ -0,0 +1,2 @@
+----------
+--> j is 1
diff --git a/libs/libtpl-1.5/tests/test53 b/libs/libtpl-1.5/tests/test53
new file mode 100755 (executable)
index 0000000..042b512
Binary files /dev/null and b/libs/libtpl-1.5/tests/test53 differ
diff --git a/libs/libtpl-1.5/tests/test53.ans b/libs/libtpl-1.5/tests/test53.ans
new file mode 100755 (executable)
index 0000000..eb90ac5
--- /dev/null
@@ -0,0 +1,3 @@
+----------
+--> j is 1
+----------
diff --git a/libs/libtpl-1.5/tests/test53.c b/libs/libtpl-1.5/tests/test53.c
new file mode 100755 (executable)
index 0000000..311556f
--- /dev/null
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int j;
+
+    tn = tpl_map("A(A(i))",&j);
+
+    j=1;
+    tpl_pack(tn,2);
+    tpl_pack(tn,1);
+    /* j=2; */
+    /* tpl_pack(tn,2); */
+    tpl_pack(tn,1);  /* pack zero-length nested array */
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test53.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(A(i))",&j);
+    tpl_load(tn, TPL_FILE, "/tmp/test53.tpl");
+    while(tpl_unpack(tn,1) > 0) {
+        printf("----------\n");
+        while(tpl_unpack(tn,2) > 0) {
+            printf("--> j is %d\n", j);
+        }
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test53.out b/libs/libtpl-1.5/tests/test53.out
new file mode 100644 (file)
index 0000000..eb90ac5
--- /dev/null
@@ -0,0 +1,3 @@
+----------
+--> j is 1
+----------
diff --git a/libs/libtpl-1.5/tests/test54 b/libs/libtpl-1.5/tests/test54
new file mode 100755 (executable)
index 0000000..94b05f4
Binary files /dev/null and b/libs/libtpl-1.5/tests/test54 differ
diff --git a/libs/libtpl-1.5/tests/test54.ans b/libs/libtpl-1.5/tests/test54.ans
new file mode 100755 (executable)
index 0000000..5125c4f
--- /dev/null
@@ -0,0 +1,2 @@
+tpl_mem_gather aborted by app callback
+tpl_gather_mem returned <= 0, exiting
diff --git a/libs/libtpl-1.5/tests/test54.c b/libs/libtpl-1.5/tests/test54.c
new file mode 100755 (executable)
index 0000000..0eeccea
--- /dev/null
@@ -0,0 +1,63 @@
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "tpl.h"
+
+#define DEBUG 0
+#define FILE_BUFLEN 500
+
+extern tpl_hook_t tpl_hook;
+int num_tpls = 0, sum_tpls = 0;
+
+int tpl_cb(void *tpl, size_t tpllen, void*data) {
+    int i;
+    tpl_node *tn;
+
+    tpl_hook.oops = printf;
+
+    if (DEBUG) printf("obtained tpl of length %d\n", (int)tpllen);
+    tn = tpl_map("A(i)", &i);
+    tpl_load(tn, TPL_MEM, tpl, tpllen);
+    num_tpls++;
+    while (tpl_unpack(tn,1) > 0) sum_tpls += i;
+    tpl_free(tn); 
+    /* this next line is a hack to test the callback's ability
+     * to abort further tpl processing by returning < 0 */
+    if (num_tpls == 3) return -1;
+    return 0;
+    
+}
+
+int main(int argc, char *argv[]) {
+    char *files[] = {"test54_0.tpl", "test54_1.tpl", "test54_2.tpl", "test54_3.tpl","test54_4.tpl", NULL};
+    char **f;
+    char buf[FILE_BUFLEN];
+    int rc,fd;
+    tpl_gather_t *gs=NULL;
+
+    for (f = files; *f; f++) {
+        if (DEBUG) printf("file is %s\n", *f);
+        if ( ( fd = open(*f, O_RDONLY) ) == -1) {
+            printf("error - can't open %s: %s\n", *f, strerror(errno));
+            exit(-1);
+        }
+        rc = read(fd,&buf,FILE_BUFLEN);  /* read whole file (no points for style) */
+        if (rc == -1) {
+            printf("error - can't read %s: %s\n", *f, strerror(errno));
+            exit(-1);
+        }
+        if (tpl_gather(TPL_GATHER_MEM,buf, rc, &gs, tpl_cb, NULL) <= 0) {
+            printf("tpl_gather_mem returned <= 0, exiting\n");
+            exit(-1);
+        }
+        close(fd);
+    }
+    printf("num_tpls: %d, sum: %d\n", num_tpls, sum_tpls);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test54.out b/libs/libtpl-1.5/tests/test54.out
new file mode 100644 (file)
index 0000000..5125c4f
--- /dev/null
@@ -0,0 +1,2 @@
+tpl_mem_gather aborted by app callback
+tpl_gather_mem returned <= 0, exiting
diff --git a/libs/libtpl-1.5/tests/test54_0.tpl b/libs/libtpl-1.5/tests/test54_0.tpl
new file mode 100755 (executable)
index 0000000..a811f62
Binary files /dev/null and b/libs/libtpl-1.5/tests/test54_0.tpl differ
diff --git a/libs/libtpl-1.5/tests/test54_1.tpl b/libs/libtpl-1.5/tests/test54_1.tpl
new file mode 100755 (executable)
index 0000000..b056e6b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test54_1.tpl differ
diff --git a/libs/libtpl-1.5/tests/test54_2.tpl b/libs/libtpl-1.5/tests/test54_2.tpl
new file mode 100755 (executable)
index 0000000..328940b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test54_2.tpl differ
diff --git a/libs/libtpl-1.5/tests/test54_3.tpl b/libs/libtpl-1.5/tests/test54_3.tpl
new file mode 100755 (executable)
index 0000000..bb74463
Binary files /dev/null and b/libs/libtpl-1.5/tests/test54_3.tpl differ
diff --git a/libs/libtpl-1.5/tests/test54_4.tpl b/libs/libtpl-1.5/tests/test54_4.tpl
new file mode 100755 (executable)
index 0000000..0219500
Binary files /dev/null and b/libs/libtpl-1.5/tests/test54_4.tpl differ
diff --git a/libs/libtpl-1.5/tests/test55 b/libs/libtpl-1.5/tests/test55
new file mode 100755 (executable)
index 0000000..c64d022
Binary files /dev/null and b/libs/libtpl-1.5/tests/test55 differ
diff --git a/libs/libtpl-1.5/tests/test55.ans b/libs/libtpl-1.5/tests/test55.ans
new file mode 100755 (executable)
index 0000000..f840753
--- /dev/null
@@ -0,0 +1,3 @@
+tpl_fd_gather aborted by app callback
+2 tpls gathered.
+499545 is their sum.
diff --git a/libs/libtpl-1.5/tests/test55.c b/libs/libtpl-1.5/tests/test55.c
new file mode 100755 (executable)
index 0000000..94bdde7
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include "tpl.h"
+
+#define DEBUG 0
+
+extern tpl_hook_t tpl_hook;
+int num_tpls = 0, sum_tpls = 0;
+
+int tpl_cb(void *tpl, size_t tpllen, void*data) {
+    int i;
+    tpl_node *tn;
+
+    tpl_hook.oops = printf;
+
+    if (DEBUG) printf("obtained tpl of length %d\n", (int)tpllen);
+    tn = tpl_map("A(i)", &i);
+    tpl_load(tn, TPL_MEM, tpl, tpllen);
+    num_tpls++;
+    while (tpl_unpack(tn,1) > 0) sum_tpls += i;
+    tpl_free(tn); 
+    /* this next line is a hack to test the callback's ability
+     * to abort further tpl processing by returning < 0 */
+    if (num_tpls == 1) return -1;
+    return 0;
+    
+}
+
+int main() {
+    FILE *f1,*f2;
+    int fdflags,fd,fd1,fd2;
+    int selrc, maxfd;
+    tpl_gather_t *gs1=NULL,*gs2=NULL,**gs;
+    struct timeval tv;
+    fd_set rset;
+
+
+    f1 = popen("cat test26_0.tpl;sleep 1; cat test26_1.tpl", "r");
+    fd1 = fileno(f1); 
+    fdflags = fcntl(fd1, F_GETFL, 0);
+    fcntl( fd1, F_SETFL, fdflags | O_NONBLOCK);
+
+    f2 = popen("cat test26_2.tpl;sleep 1; cat test26_3.tpl", "r");
+    fd2 = fileno(f2); 
+    fdflags = fcntl(fd2, F_GETFL, 0);
+    fcntl( fd2, F_SETFL, fdflags | O_NONBLOCK);
+
+    while (1) {
+        FD_ZERO( &rset );
+        if (fd1 >= 0) FD_SET( fd1, &rset );
+        if (fd2 >= 0) FD_SET( fd2, &rset );
+
+        if (fd1 == -1 && fd2 == -1) {
+            printf("%d tpls gathered.\n",num_tpls);
+            printf("%d is their sum.\n",sum_tpls);
+            return(0);
+        }
+
+        maxfd=0;
+        if (fd1>maxfd) maxfd = fd1;
+        if (fd2>maxfd) maxfd = fd2;
+
+        tv.tv_sec = 5;
+        tv.tv_usec = 0;
+
+        selrc = select(maxfd+1, &rset, NULL, NULL, &tv );
+        if (selrc == -1) {
+           perror("select()");
+        } else if (selrc) {
+            for(fd=0;fd<maxfd+1;fd++) {
+                if ( FD_ISSET(fd, &rset) ) {
+                    if (DEBUG) printf("fd %d readable\n", fd);
+                    gs = (fd1 == fd) ? &gs1 : &gs2;
+                    if (tpl_gather(TPL_GATHER_NONBLOCKING,fd,gs,tpl_cb,NULL) <= 0) {
+                        if (fd1 == fd) {pclose(f1); fd1 = -1; }
+                        if (fd2 == fd) {pclose(f2); fd2 = -1; }
+                    } else {
+                        if (DEBUG) printf("tpl_gather >0\n");
+                    }
+                }
+            }
+        } else {
+            if (DEBUG) printf("timeout\n");  
+        }
+    }
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test55.out b/libs/libtpl-1.5/tests/test55.out
new file mode 100644 (file)
index 0000000..f840753
--- /dev/null
@@ -0,0 +1,3 @@
+tpl_fd_gather aborted by app callback
+2 tpls gathered.
+499545 is their sum.
diff --git a/libs/libtpl-1.5/tests/test55_0.tpl b/libs/libtpl-1.5/tests/test55_0.tpl
new file mode 100755 (executable)
index 0000000..a811f62
Binary files /dev/null and b/libs/libtpl-1.5/tests/test55_0.tpl differ
diff --git a/libs/libtpl-1.5/tests/test55_1.tpl b/libs/libtpl-1.5/tests/test55_1.tpl
new file mode 100755 (executable)
index 0000000..85ae076
Binary files /dev/null and b/libs/libtpl-1.5/tests/test55_1.tpl differ
diff --git a/libs/libtpl-1.5/tests/test55_2.tpl b/libs/libtpl-1.5/tests/test55_2.tpl
new file mode 100755 (executable)
index 0000000..73e62d3
Binary files /dev/null and b/libs/libtpl-1.5/tests/test55_2.tpl differ
diff --git a/libs/libtpl-1.5/tests/test55_3.tpl b/libs/libtpl-1.5/tests/test55_3.tpl
new file mode 100755 (executable)
index 0000000..bb209fc
Binary files /dev/null and b/libs/libtpl-1.5/tests/test55_3.tpl differ
diff --git a/libs/libtpl-1.5/tests/test56 b/libs/libtpl-1.5/tests/test56
new file mode 100755 (executable)
index 0000000..20e3e32
Binary files /dev/null and b/libs/libtpl-1.5/tests/test56 differ
diff --git a/libs/libtpl-1.5/tests/test56.ans b/libs/libtpl-1.5/tests/test56.ans
new file mode 100755 (executable)
index 0000000..f0746c8
--- /dev/null
@@ -0,0 +1,4 @@
+hs2.s1 length: 5
+hs2.s1: draco
+hs2.s2 length: 2
+hs2.s2: po
diff --git a/libs/libtpl-1.5/tests/test56.c b/libs/libtpl-1.5/tests/test56.c
new file mode 100755 (executable)
index 0000000..e0de8e6
--- /dev/null
@@ -0,0 +1,42 @@
+#include "tpl.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define S1_LEN 6
+#define S2_LEN 4
+
+struct has_strings {
+    char a;
+    char s1[S1_LEN];
+    char s2[S2_LEN];
+};
+
+int main(int argc,char*argv[]) {
+    tpl_node *tn;
+    struct has_strings hs,hs2;
+    void *img;
+    size_t sz;
+
+    strncpy(hs.s1, "draco",S1_LEN);
+    strncpy(hs.s2, "po",S2_LEN);
+
+    tn = tpl_map("c#c#", hs.s1, S1_LEN, hs.s2, S2_LEN);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_MEM,&img,&sz);
+    tpl_free(tn);
+
+    /* unpack */
+
+    tn = tpl_map("c#c#", hs2.s1, S1_LEN, hs2.s2, S2_LEN);
+    tpl_load(tn,TPL_MEM,img,sz);
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+    free(img);
+
+    printf("hs2.s1 length: %d\n", (int)strlen(hs2.s1));
+    printf("hs2.s1: %s\n", hs2.s1);
+    printf("hs2.s2 length: %d\n", (int)strlen(hs2.s2));
+    printf("hs2.s2: %s\n", hs2.s2);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test56.out b/libs/libtpl-1.5/tests/test56.out
new file mode 100644 (file)
index 0000000..f0746c8
--- /dev/null
@@ -0,0 +1,4 @@
+hs2.s1 length: 5
+hs2.s1: draco
+hs2.s2 length: 2
+hs2.s2: po
diff --git a/libs/libtpl-1.5/tests/test57 b/libs/libtpl-1.5/tests/test57
new file mode 100755 (executable)
index 0000000..63980a5
Binary files /dev/null and b/libs/libtpl-1.5/tests/test57 differ
diff --git a/libs/libtpl-1.5/tests/test57.ans b/libs/libtpl-1.5/tests/test57.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test57.c b/libs/libtpl-1.5/tests/test57.c
new file mode 100755 (executable)
index 0000000..43bed41
--- /dev/null
@@ -0,0 +1,28 @@
+#include "tpl.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define S1_LEN 6
+#define S2_LEN 4
+
+struct has_strings {
+    char a;
+    char s1[S1_LEN];
+    char s2[S2_LEN];
+};
+
+int main(int argc,char*argv[]) {
+    tpl_node *tn;
+    struct has_strings hs;
+
+    strncpy(hs.s1, "draco",S1_LEN);
+    strncpy(hs.s2, "po",S2_LEN);
+
+    tn = tpl_map("c#c#", hs.s1, S1_LEN, hs.s2, S2_LEN);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test57.tpl");
+    tpl_free(tn);
+
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test57.out b/libs/libtpl-1.5/tests/test57.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test58 b/libs/libtpl-1.5/tests/test58
new file mode 100755 (executable)
index 0000000..a5c5a86
Binary files /dev/null and b/libs/libtpl-1.5/tests/test58 differ
diff --git a/libs/libtpl-1.5/tests/test58.ans b/libs/libtpl-1.5/tests/test58.ans
new file mode 100755 (executable)
index 0000000..f235fc6
--- /dev/null
@@ -0,0 +1,4 @@
+hs.s1 length: 5
+hs.s1: draco
+hs.s2 length: 2
+hs.s2: po
diff --git a/libs/libtpl-1.5/tests/test58.c b/libs/libtpl-1.5/tests/test58.c
new file mode 100755 (executable)
index 0000000..15f875e
--- /dev/null
@@ -0,0 +1,30 @@
+#include "tpl.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define S1_LEN 6
+#define S2_LEN 4
+
+struct has_strings {
+    char a;
+    char s1[S1_LEN];
+    char s2[S2_LEN];
+};
+
+int main(int argc,char*argv[]) {
+    tpl_node *tn;
+    struct has_strings hs;
+
+    tn = tpl_map("c#c#", hs.s1, S1_LEN, hs.s2, S2_LEN);
+    tpl_load(tn,TPL_FILE,"/tmp/test57.tpl");
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+
+    printf("hs.s1 length: %d\n", (int)strlen(hs.s1));
+    printf("hs.s1: %s\n", hs.s1);
+    printf("hs.s2 length: %d\n", (int)strlen(hs.s2));
+    printf("hs.s2: %s\n", hs.s2);
+
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test58.out b/libs/libtpl-1.5/tests/test58.out
new file mode 100644 (file)
index 0000000..f235fc6
--- /dev/null
@@ -0,0 +1,4 @@
+hs.s1 length: 5
+hs.s1: draco
+hs.s2 length: 2
+hs.s2: po
diff --git a/libs/libtpl-1.5/tests/test59 b/libs/libtpl-1.5/tests/test59
new file mode 100755 (executable)
index 0000000..4cd0109
Binary files /dev/null and b/libs/libtpl-1.5/tests/test59 differ
diff --git a/libs/libtpl-1.5/tests/test59.ans b/libs/libtpl-1.5/tests/test59.ans
new file mode 100755 (executable)
index 0000000..11e5c1c
--- /dev/null
@@ -0,0 +1,6 @@
+hs2.a: t
+hs2.s1 length: 5
+hs2.s1: draco
+hs2.b: h
+hs2.s2 length: 2
+hs2.s2: po
diff --git a/libs/libtpl-1.5/tests/test59.c b/libs/libtpl-1.5/tests/test59.c
new file mode 100755 (executable)
index 0000000..bd394f1
--- /dev/null
@@ -0,0 +1,47 @@
+#include "tpl.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define S1_LEN 6
+#define S2_LEN 4
+
+struct has_strings {
+    char a;
+    char s1[S1_LEN];
+    char b;
+    char s2[S2_LEN];
+};
+
+int main(int argc,char*argv[]) {
+    tpl_node *tn;
+    struct has_strings hs,hs2;
+    void *img;
+    size_t sz;
+
+    strncpy(hs.s1, "draco",S1_LEN);
+    strncpy(hs.s2, "po",S2_LEN);
+    hs.a = 't';
+    hs.b = 'h';
+
+    tn = tpl_map("cc#cc#", &hs.a, hs.s1, S1_LEN, &hs.b, hs.s2, S2_LEN);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_MEM,&img,&sz);
+    tpl_free(tn);
+
+    /* unpack */
+
+    tn = tpl_map("cc#cc#", &hs2.a, hs2.s1, S1_LEN, &hs2.b, hs2.s2, S2_LEN);
+    tpl_load(tn,TPL_MEM,img,sz);
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+    free(img);
+
+    printf("hs2.a: %c\n", hs2.a);
+    printf("hs2.s1 length: %d\n", (int)strlen(hs2.s1));
+    printf("hs2.s1: %s\n", hs2.s1);
+    printf("hs2.b: %c\n", hs2.b);
+    printf("hs2.s2 length: %d\n", (int)strlen(hs2.s2));
+    printf("hs2.s2: %s\n", hs2.s2);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test59.out b/libs/libtpl-1.5/tests/test59.out
new file mode 100644 (file)
index 0000000..11e5c1c
--- /dev/null
@@ -0,0 +1,6 @@
+hs2.a: t
+hs2.s1 length: 5
+hs2.s1: draco
+hs2.b: h
+hs2.s2 length: 2
+hs2.s2: po
diff --git a/libs/libtpl-1.5/tests/test6 b/libs/libtpl-1.5/tests/test6
new file mode 100755 (executable)
index 0000000..0760800
Binary files /dev/null and b/libs/libtpl-1.5/tests/test6 differ
diff --git a/libs/libtpl-1.5/tests/test6.ans b/libs/libtpl-1.5/tests/test6.ans
new file mode 100755 (executable)
index 0000000..e972e9f
--- /dev/null
@@ -0,0 +1 @@
+t is hello, world!
diff --git a/libs/libtpl-1.5/tests/test6.c b/libs/libtpl-1.5/tests/test6.c
new file mode 100755 (executable)
index 0000000..da3aec5
--- /dev/null
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    char *s,*t;
+    void *addr;
+    int sz;
+
+    tn = tpl_map("s",&s);
+    s = "hello, world!";
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_MEM,&addr,&sz);
+    tpl_free(tn);
+
+    tn = tpl_map("s",&t);
+    tpl_load(tn,TPL_MEM,addr,sz);
+    tpl_unpack(tn,0);
+    printf("t is %s\n", t);
+    free(t);
+    tpl_free(tn);
+    free(addr);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test6.out b/libs/libtpl-1.5/tests/test6.out
new file mode 100644 (file)
index 0000000..e972e9f
--- /dev/null
@@ -0,0 +1 @@
+t is hello, world!
diff --git a/libs/libtpl-1.5/tests/test60 b/libs/libtpl-1.5/tests/test60
new file mode 100755 (executable)
index 0000000..dac0a36
Binary files /dev/null and b/libs/libtpl-1.5/tests/test60 differ
diff --git a/libs/libtpl-1.5/tests/test60.ans b/libs/libtpl-1.5/tests/test60.ans
new file mode 100755 (executable)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test60.c b/libs/libtpl-1.5/tests/test60.c
new file mode 100755 (executable)
index 0000000..b797bf5
--- /dev/null
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map("A(i)",&i);
+    for(i=0;i<10;i++) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FILE,"/tmp/test60.tpl");
+
+    /* test load-after-pack: implicit free via tpl_free_keep_map() */
+    tpl_load(tn,TPL_FILE,"/tmp/test60.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test60.out b/libs/libtpl-1.5/tests/test60.out
new file mode 100644 (file)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test61 b/libs/libtpl-1.5/tests/test61
new file mode 100755 (executable)
index 0000000..a0683bb
Binary files /dev/null and b/libs/libtpl-1.5/tests/test61 differ
diff --git a/libs/libtpl-1.5/tests/test61.ans b/libs/libtpl-1.5/tests/test61.ans
new file mode 100755 (executable)
index 0000000..71580ae
--- /dev/null
@@ -0,0 +1,20 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
+i is 10
+i is 11
+i is 12
+i is 13
+i is 14
+i is 15
+i is 16
+i is 17
+i is 18
+i is 19
diff --git a/libs/libtpl-1.5/tests/test61.c b/libs/libtpl-1.5/tests/test61.c
new file mode 100755 (executable)
index 0000000..efa64ff
--- /dev/null
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test61_0.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+
+    /* test load-then-load: implicit free via tpl_free_keep_map */
+    tpl_load(tn, TPL_FILE,"test61_1.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test61.out b/libs/libtpl-1.5/tests/test61.out
new file mode 100644 (file)
index 0000000..71580ae
--- /dev/null
@@ -0,0 +1,20 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
+i is 10
+i is 11
+i is 12
+i is 13
+i is 14
+i is 15
+i is 16
+i is 17
+i is 18
+i is 19
diff --git a/libs/libtpl-1.5/tests/test61_0.tpl b/libs/libtpl-1.5/tests/test61_0.tpl
new file mode 100755 (executable)
index 0000000..d928efa
Binary files /dev/null and b/libs/libtpl-1.5/tests/test61_0.tpl differ
diff --git a/libs/libtpl-1.5/tests/test61_1.tpl b/libs/libtpl-1.5/tests/test61_1.tpl
new file mode 100755 (executable)
index 0000000..0ee24de
Binary files /dev/null and b/libs/libtpl-1.5/tests/test61_1.tpl differ
diff --git a/libs/libtpl-1.5/tests/test62 b/libs/libtpl-1.5/tests/test62
new file mode 100755 (executable)
index 0000000..4e07a1c
Binary files /dev/null and b/libs/libtpl-1.5/tests/test62 differ
diff --git a/libs/libtpl-1.5/tests/test62.ans b/libs/libtpl-1.5/tests/test62.ans
new file mode 100755 (executable)
index 0000000..61287c2
--- /dev/null
@@ -0,0 +1,20 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
+i is 0
+i is -1
+i is -2
+i is -3
+i is -4
+i is -5
+i is -6
+i is -7
+i is -8
+i is -9
diff --git a/libs/libtpl-1.5/tests/test62.c b/libs/libtpl-1.5/tests/test62.c
new file mode 100755 (executable)
index 0000000..18797ee
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test62_0.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+
+    /* test load-then-pack (then load): implicit free via tpl_free_keep_map */
+    for(i=0;i>-10;i--) tpl_pack(tn,1);
+    tpl_dump(tn, TPL_FILE,"/tmp/test62_1.tpl");
+    tpl_load(tn,TPL_FILE,"/tmp/test62_1.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test62.out b/libs/libtpl-1.5/tests/test62.out
new file mode 100644 (file)
index 0000000..61287c2
--- /dev/null
@@ -0,0 +1,20 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
+i is 0
+i is -1
+i is -2
+i is -3
+i is -4
+i is -5
+i is -6
+i is -7
+i is -8
+i is -9
diff --git a/libs/libtpl-1.5/tests/test62_0.tpl b/libs/libtpl-1.5/tests/test62_0.tpl
new file mode 100755 (executable)
index 0000000..d928efa
Binary files /dev/null and b/libs/libtpl-1.5/tests/test62_0.tpl differ
diff --git a/libs/libtpl-1.5/tests/test63 b/libs/libtpl-1.5/tests/test63
new file mode 100755 (executable)
index 0000000..4f1ab38
Binary files /dev/null and b/libs/libtpl-1.5/tests/test63 differ
diff --git a/libs/libtpl-1.5/tests/test63.ans b/libs/libtpl-1.5/tests/test63.ans
new file mode 100755 (executable)
index 0000000..61287c2
--- /dev/null
@@ -0,0 +1,20 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
+i is 0
+i is -1
+i is -2
+i is -3
+i is -4
+i is -5
+i is -6
+i is -7
+i is -8
+i is -9
diff --git a/libs/libtpl-1.5/tests/test63.c b/libs/libtpl-1.5/tests/test63.c
new file mode 100755 (executable)
index 0000000..b60b8fe
--- /dev/null
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map("A(i)",&i);
+    for(i=0;i<10;i++) tpl_pack(tn,1);
+
+    /* test pack-then-unpack without dump/load; implicit dump/load*/
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+
+    /* implicit conversion back to output tpl (discards previous data in tpl */
+    for(i=0;i>-10;i--) tpl_pack(tn,1);
+
+    /* one more implicit conversion */
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test63.out b/libs/libtpl-1.5/tests/test63.out
new file mode 100644 (file)
index 0000000..61287c2
--- /dev/null
@@ -0,0 +1,20 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
+i is 0
+i is -1
+i is -2
+i is -3
+i is -4
+i is -5
+i is -6
+i is -7
+i is -8
+i is -9
diff --git a/libs/libtpl-1.5/tests/test64 b/libs/libtpl-1.5/tests/test64
new file mode 100755 (executable)
index 0000000..b6f9024
Binary files /dev/null and b/libs/libtpl-1.5/tests/test64 differ
diff --git a/libs/libtpl-1.5/tests/test64.ans b/libs/libtpl-1.5/tests/test64.ans
new file mode 100755 (executable)
index 0000000..c9162af
--- /dev/null
@@ -0,0 +1,3 @@
+s is beta
+sh.str is delta
+bin.addr is zeta, size 5
diff --git a/libs/libtpl-1.5/tests/test64.c b/libs/libtpl-1.5/tests/test64.c
new file mode 100755 (executable)
index 0000000..3800f28
--- /dev/null
@@ -0,0 +1,80 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "tpl.h"
+
+struct str_holder {
+    char str[10];
+};
+
+
+/* the real purpose of this test is to be run under dbx "check -all" 
+ * mode to ensure the level-0 data are freed when replaced (i.e. the
+ * level 0 nodes are packed more than once, this is an edge case but
+ * the required behavior is to free the previously-packed data when
+ * packing the new replacement data). Do the test for s,S,and B types.
+ */
+int main() {
+    tpl_node *tn;
+    char *s;
+    struct str_holder sh;
+    tpl_bin bin;
+
+    /* test a replacement pack (s type) of the level 0 node */
+    tn = tpl_map("s", &s);
+    s = "alpha";
+    tpl_pack(tn,0);  /* copies alpha */
+    s = "beta"; 
+    tpl_pack(tn,0);  /* should free alpha, copy beta */
+    tpl_dump(tn,TPL_FILE,"/tmp/test64_0.tpl");
+    tpl_free(tn);
+
+    /* print out dumped tpl */
+    s = "";
+    tn = tpl_map("s", &s);
+    tpl_load(tn,TPL_FILE,"/tmp/test64_0.tpl");
+    tpl_unpack(tn,0);
+    printf("s is %s\n", s);
+    free(s);
+    tpl_free(tn);
+
+    /* test replacement pack (S type) of the level 0 node */
+    tn = tpl_map("c#", sh.str, 10);
+    strncpy(sh.str, "gamma", 10);
+    tpl_pack(tn,0);  /* copies gamma */
+    strncpy(sh.str, "delta", 10);
+    tpl_pack(tn,0);  /* should free gamma, copy delta */
+    tpl_dump(tn,TPL_FILE,"/tmp/test64_1.tpl");
+    tpl_free(tn);
+
+    /* print out dumped tpl */
+    sh.str[0] = '\0';
+    tn = tpl_map("c#", sh.str, 10);
+    tpl_load(tn,TPL_FILE,"/tmp/test64_1.tpl");
+    tpl_unpack(tn,0);
+    printf("sh.str is %s\n", sh.str);
+    tpl_free(tn);
+
+    /* test replacement pack (B type) of the level 0 node */
+    tn = tpl_map("B", &bin);
+    bin.addr = "epsilon";
+    bin.sz = strlen("epsilon")+1;
+    tpl_pack(tn,0);  /* copies epsilon */
+    bin.addr = "zeta";
+    bin.sz = strlen("zeta")+1;
+    tpl_pack(tn,0);  /* should free epsilon, copy zeta */
+    tpl_dump(tn,TPL_FILE,"/tmp/test64_2.tpl");
+    tpl_free(tn);
+
+    /* print out dumped tpl */
+    bin.addr = "";
+    bin.sz = 1;
+    tn = tpl_map("B", &bin);
+    tpl_load(tn,TPL_FILE,"/tmp/test64_2.tpl");
+    tpl_unpack(tn,0);
+    printf("bin.addr is %s, size %d\n", (char*)(bin.addr), bin.sz);
+    free(bin.addr);
+    tpl_free(tn);
+    return(0);
+
+}
diff --git a/libs/libtpl-1.5/tests/test64.out b/libs/libtpl-1.5/tests/test64.out
new file mode 100644 (file)
index 0000000..c9162af
--- /dev/null
@@ -0,0 +1,3 @@
+s is beta
+sh.str is delta
+bin.addr is zeta, size 5
diff --git a/libs/libtpl-1.5/tests/test65 b/libs/libtpl-1.5/tests/test65
new file mode 100755 (executable)
index 0000000..d7405b1
Binary files /dev/null and b/libs/libtpl-1.5/tests/test65 differ
diff --git a/libs/libtpl-1.5/tests/test65.ans b/libs/libtpl-1.5/tests/test65.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test65.c b/libs/libtpl-1.5/tests/test65.c
new file mode 100755 (executable)
index 0000000..fba332e
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define TEST_LEN 10
+
+int main() {
+    tpl_node *tn;
+    int i[TEST_LEN] = {1,2,3,4,5,6,7,8,9,10};
+
+    tn = tpl_map("i#", i, TEST_LEN);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test65.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test65.out b/libs/libtpl-1.5/tests/test65.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test66 b/libs/libtpl-1.5/tests/test66
new file mode 100755 (executable)
index 0000000..94ce5d8
Binary files /dev/null and b/libs/libtpl-1.5/tests/test66 differ
diff --git a/libs/libtpl-1.5/tests/test66.ans b/libs/libtpl-1.5/tests/test66.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test66.c b/libs/libtpl-1.5/tests/test66.c
new file mode 100755 (executable)
index 0000000..d7ca519
--- /dev/null
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define TEST_LEN1 10
+#define TEST_LEN2 5
+
+int main() {
+    tpl_node *tn;
+    int i[TEST_LEN1] = {1,2,3,4,5,6,7,8,9,10};
+    int j[TEST_LEN2] = {5,4,3,2,1};
+
+    tn = tpl_map("i#i#", i, TEST_LEN1, j, TEST_LEN2);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test66.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test66.out b/libs/libtpl-1.5/tests/test66.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test67 b/libs/libtpl-1.5/tests/test67
new file mode 100755 (executable)
index 0000000..b6d5363
Binary files /dev/null and b/libs/libtpl-1.5/tests/test67 differ
diff --git a/libs/libtpl-1.5/tests/test67.ans b/libs/libtpl-1.5/tests/test67.ans
new file mode 100755 (executable)
index 0000000..3ec4355
--- /dev/null
@@ -0,0 +1,3 @@
+load succeeded
+/tmp/test67.tpl: array lengths mismatch
+load failed
diff --git a/libs/libtpl-1.5/tests/test67.c b/libs/libtpl-1.5/tests/test67.c
new file mode 100755 (executable)
index 0000000..460240f
--- /dev/null
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define TEST_LEN1 10
+#define TEST_LEN2 5
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i[TEST_LEN1] = {1,2,3,4,5,6,7,8,9,10};
+    int j[TEST_LEN2] = {5,4,3,2,1};
+
+    tpl_hook.oops = printf;  /* errors to printf */
+
+    tn = tpl_map("i#i#", i, TEST_LEN1, j, TEST_LEN2);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test67.tpl");
+    tpl_free(tn);
+
+    /* Expect success on the next line */
+    tn = tpl_map("i#i#", i, TEST_LEN1, j, TEST_LEN2);
+    if (tpl_load(tn,TPL_FILE,"/tmp/test67.tpl") < 0) {
+        printf("load failed\n");
+    } else {
+        printf("load succeeded\n");
+    }
+    tpl_free(tn);
+
+    /* Expect failure on the next line (TEST_LEN2 != TEST_LEN2-1) */
+    tn = tpl_map("i#i#", i, TEST_LEN1, j, (TEST_LEN2 - 1));
+    if (tpl_load(tn,TPL_FILE,"/tmp/test67.tpl") < 0) {
+        printf("load failed\n");
+    } else {
+        printf("load succeeded\n");
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test67.out b/libs/libtpl-1.5/tests/test67.out
new file mode 100644 (file)
index 0000000..3ec4355
--- /dev/null
@@ -0,0 +1,3 @@
+load succeeded
+/tmp/test67.tpl: array lengths mismatch
+load failed
diff --git a/libs/libtpl-1.5/tests/test68 b/libs/libtpl-1.5/tests/test68
new file mode 100755 (executable)
index 0000000..e8c337e
Binary files /dev/null and b/libs/libtpl-1.5/tests/test68 differ
diff --git a/libs/libtpl-1.5/tests/test68.ans b/libs/libtpl-1.5/tests/test68.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test68.c b/libs/libtpl-1.5/tests/test68.c
new file mode 100755 (executable)
index 0000000..2af8e59
--- /dev/null
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define TEST_LEN1 10
+#define TEST_LEN2 5
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i[TEST_LEN1] = {1,2,3,4,5,6,7,8,9,10};
+    int j[TEST_LEN2] = {5,4,3,2,1};
+    int i2[TEST_LEN1];
+    int j2[TEST_LEN2];
+    int x;
+
+    tpl_hook.oops = printf;  /* errors to printf */
+
+    tn = tpl_map("i#i#", i, TEST_LEN1, j, TEST_LEN2);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test68.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("i#i#", i2, TEST_LEN1, j2, TEST_LEN2);
+    tpl_load(tn,TPL_FILE,"/tmp/test68.tpl");
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+
+    for(x=0;x<TEST_LEN1;x++) {
+        if (i[x] != i2[x]) printf("mismatch (i)!\n");
+    }
+    for(x=0;x<TEST_LEN2;x++) {
+        if (j[x] != j2[x]) printf("mismatch (j)!\n");
+    }
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test68.out b/libs/libtpl-1.5/tests/test68.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test69 b/libs/libtpl-1.5/tests/test69
new file mode 100755 (executable)
index 0000000..7c45b13
Binary files /dev/null and b/libs/libtpl-1.5/tests/test69 differ
diff --git a/libs/libtpl-1.5/tests/test69.ans b/libs/libtpl-1.5/tests/test69.ans
new file mode 100755 (executable)
index 0000000..35775dd
--- /dev/null
@@ -0,0 +1,4 @@
+2 3 4 5 6 7 8 9 10 11 
+4 3 2 1 0 
+3 4 5 6 7 8 9 10 11 12 
+3 2 1 0 -1 
diff --git a/libs/libtpl-1.5/tests/test69.c b/libs/libtpl-1.5/tests/test69.c
new file mode 100755 (executable)
index 0000000..ad103a1
--- /dev/null
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define TEST_LEN1 10
+#define TEST_LEN2 5
+
+extern tpl_hook_t tpl_hook;
+
+int main() {
+    tpl_node *tn;
+    int i[TEST_LEN1] = {1,2,3,4,5,6,7,8,9,10};
+    int j[TEST_LEN2] = {5,4,3,2,1};
+    int i2[TEST_LEN1];
+    int j2[TEST_LEN2];
+    int x,y;
+
+    tpl_hook.oops = printf;  /* errors to printf */
+
+    tn = tpl_map("A(i#i#)", i, TEST_LEN1, j, TEST_LEN2);
+    for(y=0; y < 2; y++) {
+        for(x=0; x < TEST_LEN1; x++) i[x] += 1;
+        for(x=0; x < TEST_LEN2; x++) j[x] -= 1;
+        tpl_pack(tn,1);
+    }
+    tpl_dump(tn,TPL_FILE,"/tmp/test69.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(i#i#)", i2, TEST_LEN1, j2, TEST_LEN2);
+    tpl_load(tn,TPL_FILE,"/tmp/test69.tpl");
+    while (tpl_unpack(tn,1) > 0) {
+        for(x=0; x < TEST_LEN1; x++) printf("%d ", i2[x]);
+        printf("\n");
+        for(x=0; x < TEST_LEN2; x++) printf("%d ", j2[x]);
+        printf("\n");
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test69.out b/libs/libtpl-1.5/tests/test69.out
new file mode 100644 (file)
index 0000000..35775dd
--- /dev/null
@@ -0,0 +1,4 @@
+2 3 4 5 6 7 8 9 10 11 
+4 3 2 1 0 
+3 4 5 6 7 8 9 10 11 12 
+3 2 1 0 -1 
diff --git a/libs/libtpl-1.5/tests/test7 b/libs/libtpl-1.5/tests/test7
new file mode 100755 (executable)
index 0000000..1b46d69
Binary files /dev/null and b/libs/libtpl-1.5/tests/test7 differ
diff --git a/libs/libtpl-1.5/tests/test7.ans b/libs/libtpl-1.5/tests/test7.ans
new file mode 100755 (executable)
index 0000000..85957f3
--- /dev/null
@@ -0,0 +1,3 @@
+t is wonderful
+t is prince of peace
+t is counselor
diff --git a/libs/libtpl-1.5/tests/test7.c b/libs/libtpl-1.5/tests/test7.c
new file mode 100755 (executable)
index 0000000..707655e
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    char *strs[] = { "wonderful", "prince of peace", "counselor", NULL };
+    int i;
+    char *s, *t;
+
+    tn = tpl_map("A(s)",&s);
+    for(i=0; strs[i] != NULL; i++) {
+        s = strs[i];
+        tpl_pack(tn,1);
+    }
+    tpl_dump(tn,TPL_FILE,"/tmp/test7.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(s)",&t);
+    tpl_load(tn,TPL_FILE,"/tmp/test7.tpl");
+    while (tpl_unpack(tn,1) > 0) {
+        printf("t is %s\n", t);
+        free(t);
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test7.out b/libs/libtpl-1.5/tests/test7.out
new file mode 100644 (file)
index 0000000..85957f3
--- /dev/null
@@ -0,0 +1,3 @@
+t is wonderful
+t is prince of peace
+t is counselor
diff --git a/libs/libtpl-1.5/tests/test70 b/libs/libtpl-1.5/tests/test70
new file mode 100755 (executable)
index 0000000..ed9d7c5
Binary files /dev/null and b/libs/libtpl-1.5/tests/test70 differ
diff --git a/libs/libtpl-1.5/tests/test70.ans b/libs/libtpl-1.5/tests/test70.ans
new file mode 100755 (executable)
index 0000000..5c9557e
--- /dev/null
@@ -0,0 +1,7 @@
+a
+1
+hi
+o
+matilda
+y
+3.140000
diff --git a/libs/libtpl-1.5/tests/test70.c b/libs/libtpl-1.5/tests/test70.c
new file mode 100755 (executable)
index 0000000..1433ed4
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tpl.h"
+
+struct ms_t {
+    char c;
+    int i;
+    char s[2];
+    char o;
+    char *x;
+    char y;
+    double d;
+};
+
+int main() {
+    tpl_node *tn;
+    struct ms_t ms = {/*.c =*/ 'a', /*.i =*/ 1, /*.s =*/ {'h','i'}, /*.o =*/ 'o', /*.x =*/ "matilda", /*.y =*/ 'y', /*.d =*/ 3.14 };
+    struct ms_t ms2;
+
+    tn = tpl_map("S(cic#cscf)", &ms, 2);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test70.tpl");
+    tpl_free(tn);
+
+    memset(&ms2,0,sizeof(struct ms_t));
+    tn = tpl_map("S(cic#cscf)", &ms2, 2);
+    tpl_load(tn,TPL_FILE,"/tmp/test70.tpl");
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+    printf("%c\n%d\n%c%c\n%c\n%s\n%c\n%f\n", ms2.c, ms2.i, ms2.s[0], ms2.s[1], ms2.o, ms2.x, ms2.y, ms2.d);
+    free(ms2.x);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test70.out b/libs/libtpl-1.5/tests/test70.out
new file mode 100644 (file)
index 0000000..5c9557e
--- /dev/null
@@ -0,0 +1,7 @@
+a
+1
+hi
+o
+matilda
+y
+3.140000
diff --git a/libs/libtpl-1.5/tests/test71 b/libs/libtpl-1.5/tests/test71
new file mode 100755 (executable)
index 0000000..90106c7
Binary files /dev/null and b/libs/libtpl-1.5/tests/test71 differ
diff --git a/libs/libtpl-1.5/tests/test71.ans b/libs/libtpl-1.5/tests/test71.ans
new file mode 100755 (executable)
index 0000000..48f248c
--- /dev/null
@@ -0,0 +1,7 @@
+#
+1
+hi
+o
+matilda
+y
+3.140000
diff --git a/libs/libtpl-1.5/tests/test71.c b/libs/libtpl-1.5/tests/test71.c
new file mode 100755 (executable)
index 0000000..d58527a
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tpl.h"
+
+struct ms_t {
+    int i;
+    char s[2];
+    char o;
+    char *x;
+    char y;
+    double d;
+};
+
+int main() {
+    tpl_node *tn;
+    struct ms_t ms = { /*.i =*/ 1, /*.s =*/ {'h','i'}, /*.o =*/ 'o', /*.x =*/ "matilda", /*.y =*/ 'y', /*.d =*/ 3.14 };
+    struct ms_t ms2;
+    char b = '#', b2;
+
+    tn = tpl_map("cS(ic#cscf)", &b, &ms, 2);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test71.tpl");
+    tpl_free(tn);
+
+    memset(&ms2,0,sizeof(struct ms_t));
+    tn = tpl_map("cS(ic#cscf)", &b2, &ms2, 2);
+    tpl_load(tn,TPL_FILE,"/tmp/test71.tpl");
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+    printf("%c\n%d\n%c%c\n%c\n%s\n%c\n%f\n", b2, ms2.i, ms2.s[0], ms2.s[1], ms2.o, ms2.x, ms2.y, ms2.d);
+    free(ms2.x);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test71.out b/libs/libtpl-1.5/tests/test71.out
new file mode 100644 (file)
index 0000000..48f248c
--- /dev/null
@@ -0,0 +1,7 @@
+#
+1
+hi
+o
+matilda
+y
+3.140000
diff --git a/libs/libtpl-1.5/tests/test72 b/libs/libtpl-1.5/tests/test72
new file mode 100755 (executable)
index 0000000..444c650
Binary files /dev/null and b/libs/libtpl-1.5/tests/test72 differ
diff --git a/libs/libtpl-1.5/tests/test72.ans b/libs/libtpl-1.5/tests/test72.ans
new file mode 100755 (executable)
index 0000000..5c9557e
--- /dev/null
@@ -0,0 +1,7 @@
+a
+1
+hi
+o
+matilda
+y
+3.140000
diff --git a/libs/libtpl-1.5/tests/test72.c b/libs/libtpl-1.5/tests/test72.c
new file mode 100755 (executable)
index 0000000..afc9a26
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tpl.h"
+
+struct ms_t {
+    char c;
+    int i;
+    char s[2];
+    char o;
+    char *x;
+    char y;
+    double d;
+};
+
+int main() {
+    tpl_node *tn;
+    struct ms_t ms = {/*.c =*/ 'a', /*.i =*/ 1, /*.s =*/ {'h','i'}, /*.o =*/ 'o', /*.x =*/ "matilda", /*.y =*/ 'y', /*.d =*/ 3.14 };
+    struct ms_t ms2;
+
+    tn = tpl_map("S(cic#cscf)", &ms, 2);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test72.tpl");
+    tpl_free(tn);
+
+    memset(&ms2,0,sizeof(struct ms_t));
+    tn = tpl_map("S(cic#cscf)", &ms2, 2);
+    tpl_load(tn,TPL_FILE,"/tmp/test72.tpl");
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+    printf("%c\n%d\n%c%c\n%c\n%s\n%c\n%f\n", ms2.c, ms2.i, ms2.s[0], ms2.s[1], ms2.o, ms2.x, ms2.y, ms2.d);
+    free(ms2.x);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test72.out b/libs/libtpl-1.5/tests/test72.out
new file mode 100644 (file)
index 0000000..5c9557e
--- /dev/null
@@ -0,0 +1,7 @@
+a
+1
+hi
+o
+matilda
+y
+3.140000
diff --git a/libs/libtpl-1.5/tests/test73 b/libs/libtpl-1.5/tests/test73
new file mode 100755 (executable)
index 0000000..1c32d97
Binary files /dev/null and b/libs/libtpl-1.5/tests/test73 differ
diff --git a/libs/libtpl-1.5/tests/test73.ans b/libs/libtpl-1.5/tests/test73.ans
new file mode 100755 (executable)
index 0000000..6b1a4e6
--- /dev/null
@@ -0,0 +1,7 @@
+a
+1
+hi
+o
+matilda
+tdh
+3.140000
diff --git a/libs/libtpl-1.5/tests/test73.c b/libs/libtpl-1.5/tests/test73.c
new file mode 100755 (executable)
index 0000000..b44dafc
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tpl.h"
+
+struct ms_t {
+    char c;
+    int i;
+    char s[2];
+    char o;
+    char *x;
+    char y[3];
+    double d;
+};
+
+int main() {
+    tpl_node *tn;
+    struct ms_t ms = {/*.c =*/ 'a', /*.i =*/ 1, /*.s =*/ {'h','i'}, /*.o =*/ 'o', /*.x =*/ "matilda", /*.y =*/ {'t','d','h'}, /*.d =*/ 3.14 };
+    struct ms_t ms2;
+
+    tn = tpl_map("S(cic#csc#f)", &ms, 2, 3);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test73.tpl");
+    tpl_free(tn);
+
+    memset(&ms2,0,sizeof(struct ms_t));
+    tn = tpl_map("S(cic#csc#f)", &ms2, 2, 3);
+    tpl_load(tn,TPL_FILE,"/tmp/test73.tpl");
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+    printf("%c\n%d\n%c%c\n%c\n%s\n%c%c%c\n%f\n", ms2.c, ms2.i, ms2.s[0], ms2.s[1], ms2.o, ms2.x, ms2.y[0],ms2.y[1],ms2.y[2], ms2.d);
+    free(ms2.x);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test73.out b/libs/libtpl-1.5/tests/test73.out
new file mode 100644 (file)
index 0000000..6b1a4e6
--- /dev/null
@@ -0,0 +1,7 @@
+a
+1
+hi
+o
+matilda
+tdh
+3.140000
diff --git a/libs/libtpl-1.5/tests/test74 b/libs/libtpl-1.5/tests/test74
new file mode 100755 (executable)
index 0000000..e16a6d7
Binary files /dev/null and b/libs/libtpl-1.5/tests/test74 differ
diff --git a/libs/libtpl-1.5/tests/test74.ans b/libs/libtpl-1.5/tests/test74.ans
new file mode 100755 (executable)
index 0000000..30913cf
--- /dev/null
@@ -0,0 +1,301 @@
+1234
+0.00
+1.50
+3.00
+4.50
+6.00
+7.50
+9.00
+10.50
+12.00
+13.50
+15.00
+16.50
+18.00
+19.50
+21.00
+22.50
+24.00
+25.50
+27.00
+28.50
+30.00
+31.50
+33.00
+34.50
+36.00
+37.50
+39.00
+40.50
+42.00
+43.50
+45.00
+46.50
+48.00
+49.50
+51.00
+52.50
+54.00
+55.50
+57.00
+58.50
+60.00
+61.50
+63.00
+64.50
+66.00
+67.50
+69.00
+70.50
+72.00
+73.50
+75.00
+76.50
+78.00
+79.50
+81.00
+82.50
+84.00
+85.50
+87.00
+88.50
+90.00
+91.50
+93.00
+94.50
+96.00
+97.50
+99.00
+100.50
+102.00
+103.50
+105.00
+106.50
+108.00
+109.50
+111.00
+112.50
+114.00
+115.50
+117.00
+118.50
+120.00
+121.50
+123.00
+124.50
+126.00
+127.50
+129.00
+130.50
+132.00
+133.50
+135.00
+136.50
+138.00
+139.50
+141.00
+142.50
+144.00
+145.50
+147.00
+148.50
+150.00
+151.50
+153.00
+154.50
+156.00
+157.50
+159.00
+160.50
+162.00
+163.50
+165.00
+166.50
+168.00
+169.50
+171.00
+172.50
+174.00
+175.50
+177.00
+178.50
+180.00
+181.50
+183.00
+184.50
+186.00
+187.50
+189.00
+190.50
+192.00
+193.50
+195.00
+196.50
+198.00
+199.50
+201.00
+202.50
+204.00
+205.50
+207.00
+208.50
+210.00
+211.50
+213.00
+214.50
+216.00
+217.50
+219.00
+220.50
+222.00
+223.50
+225.00
+226.50
+228.00
+229.50
+231.00
+232.50
+234.00
+235.50
+237.00
+238.50
+240.00
+241.50
+243.00
+244.50
+246.00
+247.50
+249.00
+250.50
+252.00
+253.50
+255.00
+256.50
+258.00
+259.50
+261.00
+262.50
+264.00
+265.50
+267.00
+268.50
+270.00
+271.50
+273.00
+274.50
+276.00
+277.50
+279.00
+280.50
+282.00
+283.50
+285.00
+286.50
+288.00
+289.50
+291.00
+292.50
+294.00
+295.50
+297.00
+298.50
+0.00
+0.50
+1.00
+1.50
+2.00
+2.50
+3.00
+3.50
+4.00
+4.50
+5.00
+5.50
+6.00
+6.50
+7.00
+7.50
+8.00
+8.50
+9.00
+9.50
+10.00
+10.50
+11.00
+11.50
+12.00
+12.50
+13.00
+13.50
+14.00
+14.50
+15.00
+15.50
+16.00
+16.50
+17.00
+17.50
+18.00
+18.50
+19.00
+19.50
+20.00
+20.50
+21.00
+21.50
+22.00
+22.50
+23.00
+23.50
+24.00
+24.50
+25.00
+25.50
+26.00
+26.50
+27.00
+27.50
+28.00
+28.50
+29.00
+29.50
+30.00
+30.50
+31.00
+31.50
+32.00
+32.50
+33.00
+33.50
+34.00
+34.50
+35.00
+35.50
+36.00
+36.50
+37.00
+37.50
+38.00
+38.50
+39.00
+39.50
+40.00
+40.50
+41.00
+41.50
+42.00
+42.50
+43.00
+43.50
+44.00
+44.50
+45.00
+45.50
+46.00
+46.50
+47.00
+47.50
+48.00
+48.50
+49.00
+49.50
diff --git a/libs/libtpl-1.5/tests/test74.c b/libs/libtpl-1.5/tests/test74.c
new file mode 100755 (executable)
index 0000000..e81f84b
--- /dev/null
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <string.h>
+#include "tpl.h"
+
+#define F1_LEN 200
+#define F2_LEN 100
+
+struct ms_t {
+    int i;
+    double f1[F1_LEN];
+    double f2[F2_LEN];
+};
+
+int main() {
+    tpl_node *tn;
+    struct ms_t ms, ms2;
+    int i;
+
+    ms.i = 1234;
+    for(i=0; i < F1_LEN; i++) ms.f1[i] = i * 1.5;
+    for(i=0; i < F2_LEN; i++) ms.f2[i] = i * 0.5;
+
+    tn = tpl_map("S(if#f#)", &ms, F1_LEN, F2_LEN);
+    tpl_pack(tn,0);
+    tpl_dump(tn,TPL_FILE,"/tmp/test74.tpl");
+    tpl_free(tn);
+
+    memset(&ms2,0,sizeof(struct ms_t));
+    tn = tpl_map("S(if#f#)", &ms2, F1_LEN, F2_LEN);
+    tpl_load(tn,TPL_FILE,"/tmp/test74.tpl");
+    tpl_unpack(tn,0);
+    tpl_free(tn);
+
+    printf("%d\n", ms2.i);
+    for(i=0; i < F1_LEN; i++) printf("%.2f\n", ms2.f1[i]);
+    for(i=0; i < F2_LEN; i++) printf("%.2f\n", ms2.f2[i]);
+    
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test74.out b/libs/libtpl-1.5/tests/test74.out
new file mode 100644 (file)
index 0000000..30913cf
--- /dev/null
@@ -0,0 +1,301 @@
+1234
+0.00
+1.50
+3.00
+4.50
+6.00
+7.50
+9.00
+10.50
+12.00
+13.50
+15.00
+16.50
+18.00
+19.50
+21.00
+22.50
+24.00
+25.50
+27.00
+28.50
+30.00
+31.50
+33.00
+34.50
+36.00
+37.50
+39.00
+40.50
+42.00
+43.50
+45.00
+46.50
+48.00
+49.50
+51.00
+52.50
+54.00
+55.50
+57.00
+58.50
+60.00
+61.50
+63.00
+64.50
+66.00
+67.50
+69.00
+70.50
+72.00
+73.50
+75.00
+76.50
+78.00
+79.50
+81.00
+82.50
+84.00
+85.50
+87.00
+88.50
+90.00
+91.50
+93.00
+94.50
+96.00
+97.50
+99.00
+100.50
+102.00
+103.50
+105.00
+106.50
+108.00
+109.50
+111.00
+112.50
+114.00
+115.50
+117.00
+118.50
+120.00
+121.50
+123.00
+124.50
+126.00
+127.50
+129.00
+130.50
+132.00
+133.50
+135.00
+136.50
+138.00
+139.50
+141.00
+142.50
+144.00
+145.50
+147.00
+148.50
+150.00
+151.50
+153.00
+154.50
+156.00
+157.50
+159.00
+160.50
+162.00
+163.50
+165.00
+166.50
+168.00
+169.50
+171.00
+172.50
+174.00
+175.50
+177.00
+178.50
+180.00
+181.50
+183.00
+184.50
+186.00
+187.50
+189.00
+190.50
+192.00
+193.50
+195.00
+196.50
+198.00
+199.50
+201.00
+202.50
+204.00
+205.50
+207.00
+208.50
+210.00
+211.50
+213.00
+214.50
+216.00
+217.50
+219.00
+220.50
+222.00
+223.50
+225.00
+226.50
+228.00
+229.50
+231.00
+232.50
+234.00
+235.50
+237.00
+238.50
+240.00
+241.50
+243.00
+244.50
+246.00
+247.50
+249.00
+250.50
+252.00
+253.50
+255.00
+256.50
+258.00
+259.50
+261.00
+262.50
+264.00
+265.50
+267.00
+268.50
+270.00
+271.50
+273.00
+274.50
+276.00
+277.50
+279.00
+280.50
+282.00
+283.50
+285.00
+286.50
+288.00
+289.50
+291.00
+292.50
+294.00
+295.50
+297.00
+298.50
+0.00
+0.50
+1.00
+1.50
+2.00
+2.50
+3.00
+3.50
+4.00
+4.50
+5.00
+5.50
+6.00
+6.50
+7.00
+7.50
+8.00
+8.50
+9.00
+9.50
+10.00
+10.50
+11.00
+11.50
+12.00
+12.50
+13.00
+13.50
+14.00
+14.50
+15.00
+15.50
+16.00
+16.50
+17.00
+17.50
+18.00
+18.50
+19.00
+19.50
+20.00
+20.50
+21.00
+21.50
+22.00
+22.50
+23.00
+23.50
+24.00
+24.50
+25.00
+25.50
+26.00
+26.50
+27.00
+27.50
+28.00
+28.50
+29.00
+29.50
+30.00
+30.50
+31.00
+31.50
+32.00
+32.50
+33.00
+33.50
+34.00
+34.50
+35.00
+35.50
+36.00
+36.50
+37.00
+37.50
+38.00
+38.50
+39.00
+39.50
+40.00
+40.50
+41.00
+41.50
+42.00
+42.50
+43.00
+43.50
+44.00
+44.50
+45.00
+45.50
+46.00
+46.50
+47.00
+47.50
+48.00
+48.50
+49.00
+49.50
diff --git a/libs/libtpl-1.5/tests/test75 b/libs/libtpl-1.5/tests/test75
new file mode 100755 (executable)
index 0000000..d9919fc
Binary files /dev/null and b/libs/libtpl-1.5/tests/test75 differ
diff --git a/libs/libtpl-1.5/tests/test75.ans b/libs/libtpl-1.5/tests/test75.ans
new file mode 100755 (executable)
index 0000000..43fce23
--- /dev/null
@@ -0,0 +1,2 @@
+string
+byte array
diff --git a/libs/libtpl-1.5/tests/test75.c b/libs/libtpl-1.5/tests/test75.c
new file mode 100755 (executable)
index 0000000..76b4fd3
--- /dev/null
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define S2_LEN 10
+
+struct example {
+    char *s1;         /* s1 is a pointer */
+    char s2[S2_LEN];  /* s2 is a byte array */
+};
+
+int main() {
+    tpl_node *tn;
+    int i;
+    struct example dst, src = {
+        /* .s1 = */ "string", 
+        /* .s2 = */ {'b','y','t','e',' ','a','r','r','a','y'}
+    };
+
+    tn = tpl_map( "sc#", &src.s1, &src.s2, S2_LEN);
+    tpl_pack( tn, 0 );  
+    tpl_dump( tn, TPL_FILE, "/tmp/test75.tpl" );
+    tpl_free( tn );
+
+    /* unpack it now into another struct */
+
+    tn = tpl_map( "sc#", &dst.s1, &dst.s2, S2_LEN);
+    tpl_load( tn, TPL_FILE, "/tmp/test75.tpl" );
+    tpl_unpack( tn, 0 );
+    tpl_free( tn );
+    printf("%s\n", dst.s1);
+    for(i=0; i < S2_LEN; i++) printf("%c", dst.s2[i]);
+    printf("\n");
+
+    free(dst.s1);   /* tpl allocated it for us; we must free it */
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test75.out b/libs/libtpl-1.5/tests/test75.out
new file mode 100644 (file)
index 0000000..43fce23
--- /dev/null
@@ -0,0 +1,2 @@
+string
+byte array
diff --git a/libs/libtpl-1.5/tests/test76 b/libs/libtpl-1.5/tests/test76
new file mode 100755 (executable)
index 0000000..67c28b7
Binary files /dev/null and b/libs/libtpl-1.5/tests/test76 differ
diff --git a/libs/libtpl-1.5/tests/test76.ans b/libs/libtpl-1.5/tests/test76.ans
new file mode 100755 (executable)
index 0000000..43fce23
--- /dev/null
@@ -0,0 +1,2 @@
+string
+byte array
diff --git a/libs/libtpl-1.5/tests/test76.c b/libs/libtpl-1.5/tests/test76.c
new file mode 100755 (executable)
index 0000000..cb57d22
--- /dev/null
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define S2_LEN 10
+
+struct example {
+    char *s1;         /* s1 is a pointer */
+    char s2[S2_LEN];  /* s2 is a byte array */
+};
+
+int main() {
+    tpl_node *tn;
+    int i;
+    struct example dst, src = {
+        /* .s1 = */ "string",
+        /* .s2 = */ {'b','y','t','e',' ','a','r','r','a','y'}
+    };
+
+    tn = tpl_map( "S(sc#)", &src, S2_LEN);   /* NOTE S(...) */
+    tpl_pack( tn, 0 );
+    tpl_dump( tn, TPL_FILE, "/tmp/test76.tpl" );
+    tpl_free( tn );
+
+    /* unpack it now into another struct */
+
+    tn = tpl_map( "S(sc#)", &dst, S2_LEN);   /* NOTE S(...) */
+    tpl_load( tn, TPL_FILE, "/tmp/test76.tpl" );
+    tpl_unpack( tn, 0 );
+    tpl_free( tn );
+
+    printf("%s\n", dst.s1);
+    for(i=0; i < S2_LEN; i++) printf("%c", dst.s2[i]);
+    printf("\n");
+
+    free(dst.s1);   /* tpl allocated it for us; we must free it */
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test76.out b/libs/libtpl-1.5/tests/test76.out
new file mode 100644 (file)
index 0000000..43fce23
--- /dev/null
@@ -0,0 +1,2 @@
+string
+byte array
diff --git a/libs/libtpl-1.5/tests/test77 b/libs/libtpl-1.5/tests/test77
new file mode 100755 (executable)
index 0000000..a1bfd3a
Binary files /dev/null and b/libs/libtpl-1.5/tests/test77 differ
diff --git a/libs/libtpl-1.5/tests/test77.ans b/libs/libtpl-1.5/tests/test77.ans
new file mode 100755 (executable)
index 0000000..43fce23
--- /dev/null
@@ -0,0 +1,2 @@
+string
+byte array
diff --git a/libs/libtpl-1.5/tests/test77.c b/libs/libtpl-1.5/tests/test77.c
new file mode 100755 (executable)
index 0000000..58b41b5
--- /dev/null
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+#define S2_LEN 10
+
+struct example {
+    char *s1;         /* s1 is a pointer */
+    char s2[S2_LEN];  /* s2 is a byte array */
+};
+
+int main() {
+    tpl_node *tn;
+    int i;
+    struct example dst, src = {
+        /* .s1 = */ "string",
+        /* .s2 = */ {'b','y','t','e',' ','a','r','r','a','y'}
+    };
+
+    tn = tpl_map( "S(sc#)", &src, S2_LEN);   /* NOTE S(...) */
+    tpl_pack( tn, 0 );
+    tpl_dump( tn, TPL_FILE, "/tmp/test77.tpl" );
+    tpl_free( tn );
+
+    /* unpack it now into another struct */
+
+    tn = tpl_map( "S(sc#)", &dst, S2_LEN);   
+    tpl_load( tn, TPL_FILE, "/tmp/test77.tpl" );
+    tpl_unpack( tn, 0 );
+    tpl_free( tn );
+
+    printf("%s\n", dst.s1);
+    for(i=0; i < S2_LEN; i++) printf("%c", dst.s2[i]);
+    printf("\n");
+
+    free(dst.s1);   /* tpl allocated it for us; we must free it */
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test77.out b/libs/libtpl-1.5/tests/test77.out
new file mode 100644 (file)
index 0000000..43fce23
--- /dev/null
@@ -0,0 +1,2 @@
+string
+byte array
diff --git a/libs/libtpl-1.5/tests/test78 b/libs/libtpl-1.5/tests/test78
new file mode 100755 (executable)
index 0000000..af888db
Binary files /dev/null and b/libs/libtpl-1.5/tests/test78 differ
diff --git a/libs/libtpl-1.5/tests/test78.ans b/libs/libtpl-1.5/tests/test78.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test78.c b/libs/libtpl-1.5/tests/test78.c
new file mode 100755 (executable)
index 0000000..cbe896f
--- /dev/null
@@ -0,0 +1,23 @@
+#include "tpl.h"
+
+int main() {
+    int i;
+    char c;
+    tpl_node *tn;
+
+    tn = tpl_map("A(i)c", &i, &c);
+
+    /* pack index number 0 (char c) */
+    c = 'a';
+    tpl_pack(tn, 0);  
+   
+    /* pack A(i) (that is, index number 1) a few times */
+    i = 3;
+    tpl_pack(tn, 1);
+    i = 4;
+    tpl_pack(tn, 1);
+
+    tpl_dump(tn, TPL_FILE, "/tmp/test78.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test78.out b/libs/libtpl-1.5/tests/test78.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test79 b/libs/libtpl-1.5/tests/test79
new file mode 100755 (executable)
index 0000000..ba59967
Binary files /dev/null and b/libs/libtpl-1.5/tests/test79 differ
diff --git a/libs/libtpl-1.5/tests/test79.ans b/libs/libtpl-1.5/tests/test79.ans
new file mode 100755 (executable)
index 0000000..33ae185
--- /dev/null
@@ -0,0 +1,3 @@
+got a
+got 3
+got 4
diff --git a/libs/libtpl-1.5/tests/test79.c b/libs/libtpl-1.5/tests/test79.c
new file mode 100755 (executable)
index 0000000..15cbaa2
--- /dev/null
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    int i;
+    char c;
+    tpl_node *tn;
+
+    tn = tpl_map("A(i)c", &i, &c);
+    tpl_load(tn, TPL_FILE, "/tmp/test78.tpl");
+
+    /* unpack index number 0 (char c) */
+    tpl_unpack(tn, 0);
+    printf("got %c\n", c);
+
+    /* unpack A(i) (that is, index number 1) til we run out of elements */
+    while (tpl_unpack(tn, 1) > 0) {
+        printf("got %d\n", i);
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test79.out b/libs/libtpl-1.5/tests/test79.out
new file mode 100644 (file)
index 0000000..33ae185
--- /dev/null
@@ -0,0 +1,3 @@
+got a
+got 3
+got 4
diff --git a/libs/libtpl-1.5/tests/test8 b/libs/libtpl-1.5/tests/test8
new file mode 100755 (executable)
index 0000000..804800b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test8 differ
diff --git a/libs/libtpl-1.5/tests/test8.ans b/libs/libtpl-1.5/tests/test8.ans
new file mode 100755 (executable)
index 0000000..46603c5
--- /dev/null
@@ -0,0 +1,10 @@
+d is ff, e is 61
+d is ff, e is 62
+d is ff, e is 63
+d is ff, e is 64
+d is ff, e is 65
+d is ff, e is 66
+d is ff, e is 67
+d is ff, e is 68
+d is ff, e is 69
+d is ff, e is 6a
diff --git a/libs/libtpl-1.5/tests/test8.c b/libs/libtpl-1.5/tests/test8.c
new file mode 100755 (executable)
index 0000000..3f8067b
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    unsigned int i;
+    unsigned char b,c;
+    unsigned char d,e;
+
+    tn = tpl_map("cA(c)",&b,&c);
+    b = 255;
+    tpl_pack(tn,0);
+    for (i=0; i < 10; i++) {
+        c = 'a' + i;
+        tpl_pack(tn,1);
+    }
+    tpl_dump(tn,TPL_FILE,"/tmp/test8.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("cA(c)",&d,&e);
+    tpl_load(tn,TPL_FILE,"/tmp/test8.tpl");
+    tpl_unpack(tn,0);
+    while (tpl_unpack(tn,1) > 0) 
+        printf("d is %x, e is %x\n", (unsigned)d, (unsigned)e);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test8.out b/libs/libtpl-1.5/tests/test8.out
new file mode 100644 (file)
index 0000000..46603c5
--- /dev/null
@@ -0,0 +1,10 @@
+d is ff, e is 61
+d is ff, e is 62
+d is ff, e is 63
+d is ff, e is 64
+d is ff, e is 65
+d is ff, e is 66
+d is ff, e is 67
+d is ff, e is 68
+d is ff, e is 69
+d is ff, e is 6a
diff --git a/libs/libtpl-1.5/tests/test80 b/libs/libtpl-1.5/tests/test80
new file mode 100755 (executable)
index 0000000..7cdd125
Binary files /dev/null and b/libs/libtpl-1.5/tests/test80 differ
diff --git a/libs/libtpl-1.5/tests/test80.ans b/libs/libtpl-1.5/tests/test80.ans
new file mode 100755 (executable)
index 0000000..ee45485
--- /dev/null
@@ -0,0 +1 @@
+a 0 1 2 3 4 5 6 7 8 9 
diff --git a/libs/libtpl-1.5/tests/test80.c b/libs/libtpl-1.5/tests/test80.c
new file mode 100755 (executable)
index 0000000..17b8b4a
--- /dev/null
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "tpl.h"
+
+#define ILEN 10
+
+struct st {
+    char c;
+    int i[ILEN];
+};
+
+int main() {
+    struct st dst, s = {'a', {0,1,2,3,4,5,6,7,8,9}};
+    tpl_node *tn;
+    int j;
+
+    tn = tpl_map("A(S(ci#))", &s, ILEN);
+    tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FILE,"/tmp/test80.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(S(ci#))", &dst, ILEN);
+    tpl_load(tn,TPL_FILE,"/tmp/test80.tpl");
+    while (tpl_unpack(tn,1) > 0) {
+        printf("%c ", dst.c);
+        for(j=0;j<ILEN;j++) printf("%d ", dst.i[j]);
+        printf("\n");
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test80.out b/libs/libtpl-1.5/tests/test80.out
new file mode 100644 (file)
index 0000000..ee45485
--- /dev/null
@@ -0,0 +1 @@
+a 0 1 2 3 4 5 6 7 8 9 
diff --git a/libs/libtpl-1.5/tests/test81 b/libs/libtpl-1.5/tests/test81
new file mode 100755 (executable)
index 0000000..cf161ea
Binary files /dev/null and b/libs/libtpl-1.5/tests/test81 differ
diff --git a/libs/libtpl-1.5/tests/test81.ans b/libs/libtpl-1.5/tests/test81.ans
new file mode 100755 (executable)
index 0000000..63b077c
--- /dev/null
@@ -0,0 +1,2 @@
+a 0 1 2 3 4 5 6 7 8 9 
+b 1 2 3 4 5 6 7 8 9 10 
diff --git a/libs/libtpl-1.5/tests/test81.c b/libs/libtpl-1.5/tests/test81.c
new file mode 100755 (executable)
index 0000000..335f91c
--- /dev/null
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include "tpl.h"
+
+#define ILEN 10
+
+struct st {
+    char c;
+    int i[ILEN];
+};
+
+int main() {
+    struct st dst, s = {'a', {0,1,2,3,4,5,6,7,8,9}};
+    tpl_node *tn;
+    int j;
+
+    tn = tpl_map("A(S(ci#))", &s, ILEN);
+    tpl_pack(tn,1);
+
+    /* fiddle with the fields and pack another element */
+    s.c++;
+    for(j=0;j<ILEN;j++) s.i[j]++;
+    tpl_pack(tn,1);
+
+    tpl_dump(tn,TPL_FILE,"/tmp/test81.tpl");
+    tpl_free(tn);
+
+    tn = tpl_map("A(S(ci#))", &dst, ILEN);
+    tpl_load(tn,TPL_FILE,"/tmp/test81.tpl");
+    while (tpl_unpack(tn,1) > 0) {
+        printf("%c ", dst.c);
+        for(j=0;j<ILEN;j++) printf("%d ", dst.i[j]);
+        printf("\n");
+    }
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test81.out b/libs/libtpl-1.5/tests/test81.out
new file mode 100644 (file)
index 0000000..63b077c
--- /dev/null
@@ -0,0 +1,2 @@
+a 0 1 2 3 4 5 6 7 8 9 
+b 1 2 3 4 5 6 7 8 9 10 
diff --git a/libs/libtpl-1.5/tests/test82 b/libs/libtpl-1.5/tests/test82
new file mode 100755 (executable)
index 0000000..d6c615f
Binary files /dev/null and b/libs/libtpl-1.5/tests/test82 differ
diff --git a/libs/libtpl-1.5/tests/test82.ans b/libs/libtpl-1.5/tests/test82.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test82.c b/libs/libtpl-1.5/tests/test82.c
new file mode 100755 (executable)
index 0000000..497f98c
--- /dev/null
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include "tpl.h"
+
+#define ILEN 10
+#define KLEN 8
+#define FLEN 5
+
+struct st {
+    char c;
+    double f[FLEN];
+};
+
+int main() {
+    tpl_node *tn;
+    /* some meaningless test data */
+    struct st s = {'z', {0.9, 0.8, 0.7, 0.6, 0.5 }};
+    int j; 
+    int i[ILEN] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+    int k[KLEN] = {100, 200, 300, 400, 500, 600, 700, 800};
+    char a = '&';
+    char b = 'x';
+
+    tn = tpl_map("cA(i#)S(cf#)A(ci#)", &a, i, ILEN, &s, FLEN, &b, k, KLEN);
+    tpl_pack(tn,0);
+
+    tpl_pack(tn,1);
+    for(j=0; j < ILEN; j++) i[j]--;
+    tpl_pack(tn,1);
+    for(j=0; j < ILEN; j++) i[j]--;
+    tpl_pack(tn,1);
+
+    tpl_pack(tn,2);
+    b++;
+    for(j=0; j < KLEN; j++) k[j] += 50;  
+    tpl_pack(tn,2);
+    b++;
+    for(j=0; j < KLEN; j++) k[j] += 50; 
+    tpl_pack(tn,2);
+
+    tpl_dump(tn,TPL_FILE,"/tmp/test82.tpl");
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test82.out b/libs/libtpl-1.5/tests/test82.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test83 b/libs/libtpl-1.5/tests/test83
new file mode 100755 (executable)
index 0000000..e9e1e64
Binary files /dev/null and b/libs/libtpl-1.5/tests/test83 differ
diff --git a/libs/libtpl-1.5/tests/test83.ans b/libs/libtpl-1.5/tests/test83.ans
new file mode 100755 (executable)
index 0000000..39a07f8
--- /dev/null
@@ -0,0 +1,7 @@
+& z 0.90 0.80 0.70 0.60 0.50 
+-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 
+-2 -3 -4 -5 -6 -7 -8 -9 -10 -11 
+-3 -4 -5 -6 -7 -8 -9 -10 -11 -12 
+x 100 200 300 400 500 600 700 800 
+y 150 250 350 450 550 650 750 850 
+z 200 300 400 500 600 700 800 900 
diff --git a/libs/libtpl-1.5/tests/test83.c b/libs/libtpl-1.5/tests/test83.c
new file mode 100755 (executable)
index 0000000..8cadf29
--- /dev/null
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include "tpl.h"
+
+#define ILEN 10
+#define KLEN 8
+#define FLEN 5
+
+struct st {
+    char c;
+    double f[FLEN];
+};
+
+int main() {
+    tpl_node *tn;
+    /* some meaningless test data */
+    struct st s;
+    int j; 
+    int i[ILEN];
+    int k[KLEN];
+    char a;
+    char b;
+
+    tn = tpl_map("cA(i#)S(cf#)A(ci#)", &a, i, ILEN, &s, FLEN, &b, k, KLEN);
+    tpl_load(tn,TPL_FILE,"/tmp/test82.tpl");
+
+    tpl_unpack(tn,0);
+    printf("%c %c %.2f %.2f %.2f %.2f %.2f \n", a, s.c, s.f[0], s.f[1], s.f[2], s.f[3], s.f[4]);
+
+    while( tpl_unpack(tn,1) > 0) {
+        for(j=0;j<ILEN;j++) printf("%d ", i[j]);
+        printf("\n");
+    }
+
+    while( tpl_unpack(tn,2) > 0) {
+        printf("%c ", b);
+        for(j=0;j<KLEN;j++) printf("%d ", k[j]);
+        printf("\n");
+    }
+
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test83.out b/libs/libtpl-1.5/tests/test83.out
new file mode 100644 (file)
index 0000000..39a07f8
--- /dev/null
@@ -0,0 +1,7 @@
+& z 0.90 0.80 0.70 0.60 0.50 
+-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 
+-2 -3 -4 -5 -6 -7 -8 -9 -10 -11 
+-3 -4 -5 -6 -7 -8 -9 -10 -11 -12 
+x 100 200 300 400 500 600 700 800 
+y 150 250 350 450 550 650 750 850 
+z 200 300 400 500 600 700 800 900 
diff --git a/libs/libtpl-1.5/tests/test84 b/libs/libtpl-1.5/tests/test84
new file mode 100755 (executable)
index 0000000..ade9e78
Binary files /dev/null and b/libs/libtpl-1.5/tests/test84 differ
diff --git a/libs/libtpl-1.5/tests/test84.ans b/libs/libtpl-1.5/tests/test84.ans
new file mode 100755 (executable)
index 0000000..dd6dba0
--- /dev/null
@@ -0,0 +1,14 @@
+& z 0.90 0.80 0.70 0.60 0.50 
+-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 
+-2 -3 -4 -5 -6 -7 -8 -9 -10 -11 
+-3 -4 -5 -6 -7 -8 -9 -10 -11 -12 
+x 100 200 300 400 500 600 700 800 
+y 150 250 350 450 550 650 750 850 
+z 200 300 400 500 600 700 800 900 
+& z 0.90 0.80 0.70 0.60 0.50 
+-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 
+-2 -3 -4 -5 -6 -7 -8 -9 -10 -11 
+-3 -4 -5 -6 -7 -8 -9 -10 -11 -12 
+x 100 200 300 400 500 600 700 800 
+y 150 250 350 450 550 650 750 850 
+z 200 300 400 500 600 700 800 900 
diff --git a/libs/libtpl-1.5/tests/test84.c b/libs/libtpl-1.5/tests/test84.c
new file mode 100755 (executable)
index 0000000..b9206ce
--- /dev/null
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include "tpl.h"
+
+#define ILEN 10
+#define KLEN 8
+#define FLEN 5
+
+struct st {
+    char c;
+    double f[FLEN];
+};
+
+int main() {
+    tpl_node *tn;
+    /* some meaningless test data */
+    struct st s;
+    int j; 
+    int i[ILEN];
+    int k[KLEN];
+    char a;
+    char b;
+
+    tn = tpl_map("cA(i#)S(cf#)A(ci#)", &a, i, ILEN, &s, FLEN, &b, k, KLEN);
+    tpl_load(tn,TPL_FILE,"test84_0.tpl");
+
+    tpl_unpack(tn,0);
+    printf("%c %c %.2f %.2f %.2f %.2f %.2f \n", a, s.c, s.f[0], s.f[1], s.f[2], s.f[3], s.f[4]);
+
+    while( tpl_unpack(tn,1) > 0) {
+        for(j=0;j<ILEN;j++) printf("%d ", i[j]);
+        printf("\n");
+    }
+
+    while( tpl_unpack(tn,2) > 0) {
+        printf("%c ", b);
+        for(j=0;j<KLEN;j++) printf("%d ", k[j]);
+        printf("\n");
+    }
+
+    tpl_free(tn);
+
+    /* use the big-endian input file and repeat */
+
+    tn = tpl_map("cA(i#)S(cf#)A(ci#)", &a, i, ILEN, &s, FLEN, &b, k, KLEN);
+    tpl_load(tn,TPL_FILE,"test84_1.tpl");
+
+    tpl_unpack(tn,0);
+    printf("%c %c %.2f %.2f %.2f %.2f %.2f \n", a, s.c, s.f[0], s.f[1], s.f[2], s.f[3], s.f[4]);
+
+    while( tpl_unpack(tn,1) > 0) {
+        for(j=0;j<ILEN;j++) printf("%d ", i[j]);
+        printf("\n");
+    }
+
+    while( tpl_unpack(tn,2) > 0) {
+        printf("%c ", b);
+        for(j=0;j<KLEN;j++) printf("%d ", k[j]);
+        printf("\n");
+    }
+
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test84.out b/libs/libtpl-1.5/tests/test84.out
new file mode 100644 (file)
index 0000000..dd6dba0
--- /dev/null
@@ -0,0 +1,14 @@
+& z 0.90 0.80 0.70 0.60 0.50 
+-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 
+-2 -3 -4 -5 -6 -7 -8 -9 -10 -11 
+-3 -4 -5 -6 -7 -8 -9 -10 -11 -12 
+x 100 200 300 400 500 600 700 800 
+y 150 250 350 450 550 650 750 850 
+z 200 300 400 500 600 700 800 900 
+& z 0.90 0.80 0.70 0.60 0.50 
+-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 
+-2 -3 -4 -5 -6 -7 -8 -9 -10 -11 
+-3 -4 -5 -6 -7 -8 -9 -10 -11 -12 
+x 100 200 300 400 500 600 700 800 
+y 150 250 350 450 550 650 750 850 
+z 200 300 400 500 600 700 800 900 
diff --git a/libs/libtpl-1.5/tests/test84_0.tpl b/libs/libtpl-1.5/tests/test84_0.tpl
new file mode 100755 (executable)
index 0000000..bb934e3
Binary files /dev/null and b/libs/libtpl-1.5/tests/test84_0.tpl differ
diff --git a/libs/libtpl-1.5/tests/test84_1.tpl b/libs/libtpl-1.5/tests/test84_1.tpl
new file mode 100755 (executable)
index 0000000..bb3a40d
Binary files /dev/null and b/libs/libtpl-1.5/tests/test84_1.tpl differ
diff --git a/libs/libtpl-1.5/tests/test85 b/libs/libtpl-1.5/tests/test85
new file mode 100755 (executable)
index 0000000..3cdf5fe
Binary files /dev/null and b/libs/libtpl-1.5/tests/test85 differ
diff --git a/libs/libtpl-1.5/tests/test85.ans b/libs/libtpl-1.5/tests/test85.ans
new file mode 100755 (executable)
index 0000000..7d8448a
--- /dev/null
@@ -0,0 +1 @@
+cA(i#)S(cf#)A(ci#)
diff --git a/libs/libtpl-1.5/tests/test85.c b/libs/libtpl-1.5/tests/test85.c
new file mode 100755 (executable)
index 0000000..4a0e12c
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    char *fmt;
+    fmt = tpl_peek(TPL_FILE, "test85.tpl");
+    if (fmt) {
+        printf("%s\n",fmt);
+        free(fmt);
+    }
+    return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test85.out b/libs/libtpl-1.5/tests/test85.out
new file mode 100644 (file)
index 0000000..7d8448a
--- /dev/null
@@ -0,0 +1 @@
+cA(i#)S(cf#)A(ci#)
diff --git a/libs/libtpl-1.5/tests/test85.tpl b/libs/libtpl-1.5/tests/test85.tpl
new file mode 100755 (executable)
index 0000000..bb934e3
Binary files /dev/null and b/libs/libtpl-1.5/tests/test85.tpl differ
diff --git a/libs/libtpl-1.5/tests/test86 b/libs/libtpl-1.5/tests/test86
new file mode 100755 (executable)
index 0000000..b68dbeb
Binary files /dev/null and b/libs/libtpl-1.5/tests/test86 differ
diff --git a/libs/libtpl-1.5/tests/test86.ans b/libs/libtpl-1.5/tests/test86.ans
new file mode 100755 (executable)
index 0000000..66c7f89
--- /dev/null
@@ -0,0 +1 @@
+A(A(i))
diff --git a/libs/libtpl-1.5/tests/test86.c b/libs/libtpl-1.5/tests/test86.c
new file mode 100755 (executable)
index 0000000..b87070e
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int o,i;
+    void *addr;
+    int sz;
+    char *fmt;
+
+    tn = tpl_map("A(A(i))",&i);
+    for(o=0;o<10;o++) {
+        for(i=o; i < o+10; i++) tpl_pack(tn,2);
+        tpl_pack(tn,1);
+    }
+    tpl_dump(tn,TPL_MEM,&addr,&sz);
+    tpl_free(tn);
+
+    fmt = tpl_peek(TPL_MEM, addr, sz);
+    if (fmt) {
+        printf("%s\n",fmt);
+        free(fmt);
+    }
+    free(addr);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test86.out b/libs/libtpl-1.5/tests/test86.out
new file mode 100644 (file)
index 0000000..66c7f89
--- /dev/null
@@ -0,0 +1 @@
+A(A(i))
diff --git a/libs/libtpl-1.5/tests/test87 b/libs/libtpl-1.5/tests/test87
new file mode 100755 (executable)
index 0000000..32313a7
Binary files /dev/null and b/libs/libtpl-1.5/tests/test87 differ
diff --git a/libs/libtpl-1.5/tests/test87.ans b/libs/libtpl-1.5/tests/test87.ans
new file mode 100755 (executable)
index 0000000..494c321
--- /dev/null
@@ -0,0 +1 @@
+sum is 49995000
diff --git a/libs/libtpl-1.5/tests/test87.c b/libs/libtpl-1.5/tests/test87.c
new file mode 100755 (executable)
index 0000000..b11db98
--- /dev/null
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main() {
+    tpl_node *tn;
+    unsigned i, sum=0;
+    int fd[2], pid,rc;
+    void *img;
+    size_t sz;
+
+    pipe(fd);
+    if ( (pid = fork()) == 0) {   /* child */
+
+        rc = tpl_gather(TPL_GATHER_BLOCKING,fd[0],&img,&sz);
+        if (rc != 1) {
+            printf("error: rc non-zero: %d\n", rc);
+            exit(-1);
+        }
+        tn = tpl_map("A(u)",&i);
+        tpl_load(tn, TPL_MEM, img,sz);
+        while (tpl_unpack(tn,1) > 0) sum += i;
+        tpl_free(tn);
+        printf("sum is %d\n", sum);
+
+    } else if (pid > 0) {         /* parent */
+
+        tn = tpl_map("A(u)",&i);
+        for(i=0;i<10000;i++) tpl_pack(tn,1);
+        tpl_dump(tn,TPL_FD, fd[1] );
+        tpl_free(tn);
+
+        close(fd[1]);
+        waitpid(pid,NULL,0);
+
+    } else if (pid == -1) {
+        perror("fork error");
+    }
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test87.out b/libs/libtpl-1.5/tests/test87.out
new file mode 100644 (file)
index 0000000..494c321
--- /dev/null
@@ -0,0 +1 @@
+sum is 49995000
diff --git a/libs/libtpl-1.5/tests/test88 b/libs/libtpl-1.5/tests/test88
new file mode 100755 (executable)
index 0000000..7e665d1
Binary files /dev/null and b/libs/libtpl-1.5/tests/test88 differ
diff --git a/libs/libtpl-1.5/tests/test88.ans b/libs/libtpl-1.5/tests/test88.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test88.c b/libs/libtpl-1.5/tests/test88.c
new file mode 100755 (executable)
index 0000000..57e5e82
--- /dev/null
@@ -0,0 +1,18 @@
+#include "tpl.h"
+
+struct ms_t {
+    int i;
+    char c[3];
+    double f;
+};
+
+int main() {
+    tpl_node *tn;
+    struct ms_t ms = {1, {'a','b','c'}, 3.14};
+
+    tn = tpl_map( "S(ic#f)", &ms, 3);
+    tpl_pack( tn, 0 );
+    tpl_dump( tn, TPL_FILE, "/tmp/test88.tpl" );
+    tpl_free( tn );
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test88.out b/libs/libtpl-1.5/tests/test88.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test89 b/libs/libtpl-1.5/tests/test89
new file mode 100755 (executable)
index 0000000..5849716
Binary files /dev/null and b/libs/libtpl-1.5/tests/test89 differ
diff --git a/libs/libtpl-1.5/tests/test89.ans b/libs/libtpl-1.5/tests/test89.ans
new file mode 100755 (executable)
index 0000000..626f9b8
--- /dev/null
@@ -0,0 +1,3 @@
+1
+abc
+3.14
diff --git a/libs/libtpl-1.5/tests/test89.c b/libs/libtpl-1.5/tests/test89.c
new file mode 100755 (executable)
index 0000000..f632db4
--- /dev/null
@@ -0,0 +1,21 @@
+#include "tpl.h"
+#include <stdio.h>
+
+struct ms_t {
+    int i;
+    char c[3];
+    double f;
+};
+
+int main() {
+    tpl_node *tn;
+    struct ms_t ms;
+
+    tn = tpl_map( "S(ic#f)", &ms, 3);
+    tpl_load( tn, TPL_FILE, "/tmp/test88.tpl" );
+    tpl_unpack( tn, 0 );
+    tpl_free( tn );
+
+    printf("%d\n%c%c%c\n%.2f\n", ms.i, ms.c[0],ms.c[1],ms.c[2], ms.f);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test89.out b/libs/libtpl-1.5/tests/test89.out
new file mode 100644 (file)
index 0000000..626f9b8
--- /dev/null
@@ -0,0 +1,3 @@
+1
+abc
+3.14
diff --git a/libs/libtpl-1.5/tests/test9 b/libs/libtpl-1.5/tests/test9
new file mode 100755 (executable)
index 0000000..ed6ac3b
Binary files /dev/null and b/libs/libtpl-1.5/tests/test9 differ
diff --git a/libs/libtpl-1.5/tests/test9.ans b/libs/libtpl-1.5/tests/test9.ans
new file mode 100755 (executable)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test9.c b/libs/libtpl-1.5/tests/test9.c
new file mode 100755 (executable)
index 0000000..f4a7251
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include "tpl.h"
+
+int main() {
+    tpl_node *tn;
+    int i;
+
+    tn = tpl_map("A(i)",&i);
+    tpl_load(tn,TPL_FILE,"test9.tpl");
+    while (tpl_unpack(tn,1) > 0) printf("i is %d\n", i);
+    tpl_free(tn);
+    return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test9.out b/libs/libtpl-1.5/tests/test9.out
new file mode 100644 (file)
index 0000000..903c08c
--- /dev/null
@@ -0,0 +1,10 @@
+i is 0
+i is 1
+i is 2
+i is 3
+i is 4
+i is 5
+i is 6
+i is 7
+i is 8
+i is 9
diff --git a/libs/libtpl-1.5/tests/test9.tpl b/libs/libtpl-1.5/tests/test9.tpl
new file mode 100755 (executable)
index 0000000..d928efa
Binary files /dev/null and b/libs/libtpl-1.5/tests/test9.tpl differ
diff --git a/libs/libtpl-1.5/tests/test90 b/libs/libtpl-1.5/tests/test90
new file mode 100755 (executable)
index 0000000..8097d11
Binary files /dev/null and b/libs/libtpl-1.5/tests/test90 differ
diff --git a/libs/libtpl-1.5/tests/test90.ans b/libs/libtpl-1.5/tests/test90.ans
new file mode 100755 (executable)
index 0000000..4f2784a
--- /dev/null
@@ -0,0 +1 @@
+cn is equal to cn2
diff --git a/libs/libtpl-1.5/tests/test90.c b/libs/libtpl-1.5/tests/test90.c
new file mode 100755 (executable)
index 0000000..5c61152
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include <tpl.h>
+
+int main ( int n , char* a [ ] )
+{
+
+       tpl_node* tn ;
+       int64_t cn = 100,cn2 ;
+
+       tn = tpl_map ( "I" , &cn ) ;
+       tpl_pack ( tn , 0 ) ;
+       tpl_dump ( tn , TPL_FILE , "/tmp/test90.tpl" ) ;
+       tpl_free ( tn ) ;
+
+       tn = tpl_map ( "I" , &cn2 ) ;
+       tpl_load ( tn , TPL_FILE , "/tmp/test90.tpl" ) ;
+       tpl_unpack ( tn , 0 ) ;
+       printf("cn is %sequal to cn2\n", (cn == cn2) ? "" : "not");
+       tpl_free ( tn ) ;
+       return ( 0 ) ;
+}
diff --git a/libs/libtpl-1.5/tests/test90.out b/libs/libtpl-1.5/tests/test90.out
new file mode 100644 (file)
index 0000000..4f2784a
--- /dev/null
@@ -0,0 +1 @@
+cn is equal to cn2
diff --git a/libs/libtpl-1.5/tests/test91 b/libs/libtpl-1.5/tests/test91
new file mode 100755 (executable)
index 0000000..70108c0
Binary files /dev/null and b/libs/libtpl-1.5/tests/test91 differ
diff --git a/libs/libtpl-1.5/tests/test91.ans b/libs/libtpl-1.5/tests/test91.ans
new file mode 100755 (executable)
index 0000000..4f2784a
--- /dev/null
@@ -0,0 +1 @@
+cn is equal to cn2
diff --git a/libs/libtpl-1.5/tests/test91.c b/libs/libtpl-1.5/tests/test91.c
new file mode 100755 (executable)
index 0000000..0e9f659
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include <tpl.h>
+
+int main ( int n , char* a [ ] )
+{
+
+       tpl_node* tn ;
+       uint64_t cn = 100, cn2 ;
+
+       tn = tpl_map ( "U" , &cn ) ;
+       tpl_pack ( tn , 0 ) ;
+       tpl_dump ( tn , TPL_FILE , "/tmp/test91.tpl" ) ;
+       tpl_free ( tn ) ;
+
+       tn = tpl_map ( "U" , &cn2 ) ;
+       tpl_load ( tn , TPL_FILE , "/tmp/test91.tpl" ) ;
+       tpl_unpack ( tn , 0 ) ;
+       printf("cn is %sequal to cn2\n", (cn == cn2) ? "" : "not");
+       tpl_free ( tn ) ;
+       return ( 0 ) ;
+}
diff --git a/libs/libtpl-1.5/tests/test91.out b/libs/libtpl-1.5/tests/test91.out
new file mode 100644 (file)
index 0000000..4f2784a
--- /dev/null
@@ -0,0 +1 @@
+cn is equal to cn2
diff --git a/libs/libtpl-1.5/tests/test92 b/libs/libtpl-1.5/tests/test92
new file mode 100755 (executable)
index 0000000..96207af
Binary files /dev/null and b/libs/libtpl-1.5/tests/test92 differ
diff --git a/libs/libtpl-1.5/tests/test92.ans b/libs/libtpl-1.5/tests/test92.ans
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test92.c b/libs/libtpl-1.5/tests/test92.c
new file mode 100755 (executable)
index 0000000..55d47f7
--- /dev/null
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include <tpl.h>
+
+int main ( int n , char* a [ ] )
+{
+
+       tpl_node* tn ;
+       char c='a',c2='b',c3,c4;
+       int64_t cn = -100, cn2 ;
+       uint64_t ucn = 200, ucn2;
+
+       tn = tpl_map ( "A(cIcU)" , &c, &cn, &c2, &ucn ) ;
+       tpl_pack ( tn , 1 ) ;
+       c += 1;
+       cn -= 1;
+       c2 += 1;
+       ucn += 1;
+       tpl_pack ( tn , 1 ) ;
+       tpl_dump ( tn , TPL_FILE , "/tmp/test92.tpl" ) ;
+       tpl_free ( tn ) ;
+
+       tn = tpl_map ( "A(cIcU)" , &c3, &cn2, &c4, &ucn2 ) ;
+       tpl_load(tn,TPL_FILE,"/tmp/test92.tpl");
+       /* Hesitant to rely on portability of %lld to print int64_t.
+          At least on MinGW it is questionable. */
+       /*
+        * while (tpl_unpack(tn,1) > 0) {
+        *  printf("%c %lld %c %llu\n", c3, cn2, c4, ucn2);
+        * }
+       */
+       tpl_unpack(tn,1);
+       if (c3 != 'a' || cn2 != -100 || c4 != 'b' || ucn2 != 200) printf("unpack error 1\n");
+       tpl_unpack(tn,1);
+       if (c3 != 'b' || cn2 != -101 || c4 != 'c' || ucn2 != 201) printf("unpack error 2\n");
+       return ( 0 ) ;
+
+}
diff --git a/libs/libtpl-1.5/tests/test92.out b/libs/libtpl-1.5/tests/test92.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/libtpl-1.5/tests/test93 b/libs/libtpl-1.5/tests/test93
new file mode 100755 (executable)
index 0000000..b26847e
Binary files /dev/null and b/libs/libtpl-1.5/tests/test93 differ
diff --git a/libs/libtpl-1.5/tests/test93.ans b/libs/libtpl-1.5/tests/test93.ans
new file mode 100755 (executable)
index 0000000..8023187
--- /dev/null
@@ -0,0 +1 @@
+s is null
diff --git a/libs/libtpl-1.5/tests/test93.c b/libs/libtpl-1.5/tests/test93.c
new file mode 100755 (executable)
index 0000000..944cc76
--- /dev/null
@@ -0,0 +1,21 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename="/tmp/test93.tpl";
+int main() {
+  tpl_node *tn;
+  char *s = NULL;
+  tn = tpl_map("s", &s);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  s = (char*)0x1; /* overwritten below */
+  tn  = tpl_map("s", &s);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+  printf("s %s null\n", (s==NULL?"is":"is NOT"));
+  return(0);
+}
+
diff --git a/libs/libtpl-1.5/tests/test93.out b/libs/libtpl-1.5/tests/test93.out
new file mode 100644 (file)
index 0000000..8023187
--- /dev/null
@@ -0,0 +1 @@
+s is null
diff --git a/libs/libtpl-1.5/tests/test94 b/libs/libtpl-1.5/tests/test94
new file mode 100755 (executable)
index 0000000..4b55885
Binary files /dev/null and b/libs/libtpl-1.5/tests/test94 differ
diff --git a/libs/libtpl-1.5/tests/test94.ans b/libs/libtpl-1.5/tests/test94.ans
new file mode 100755 (executable)
index 0000000..572008b
--- /dev/null
@@ -0,0 +1,5 @@
+s is hello
+s is NULL
+s is hello
+s is NULL
+s is hello
diff --git a/libs/libtpl-1.5/tests/test94.c b/libs/libtpl-1.5/tests/test94.c
new file mode 100755 (executable)
index 0000000..43843a2
--- /dev/null
@@ -0,0 +1,26 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename="/tmp/test94.tpl";
+int main() {
+  tpl_node *tn;
+  int i;
+  char *s = NULL;
+  tn = tpl_map("A(s)", &s);
+  for(i=0;i<5;i++) {
+    s = (i&1) ? NULL : "hello"; /* odd i are NULL string */
+    tpl_pack(tn,1);
+  }
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  s = (char*)0x1; /* overwritten below */
+  tn  = tpl_map("A(s)", &s);
+  tpl_load(tn,TPL_FILE,filename);
+  while( tpl_unpack(tn,1) > 0) {
+    printf("s is %s\n", (s?s:"NULL"));
+  }
+  tpl_free(tn);
+  return(0);
+}
+
diff --git a/libs/libtpl-1.5/tests/test94.out b/libs/libtpl-1.5/tests/test94.out
new file mode 100644 (file)
index 0000000..572008b
--- /dev/null
@@ -0,0 +1,5 @@
+s is hello
+s is NULL
+s is hello
+s is NULL
+s is hello
diff --git a/libs/libtpl-1.5/tests/test95 b/libs/libtpl-1.5/tests/test95
new file mode 100755 (executable)
index 0000000..0ad6823
Binary files /dev/null and b/libs/libtpl-1.5/tests/test95 differ
diff --git a/libs/libtpl-1.5/tests/test95.ans b/libs/libtpl-1.5/tests/test95.ans
new file mode 100755 (executable)
index 0000000..9ce4720
--- /dev/null
@@ -0,0 +1,3 @@
+s1 NULL
+s2 
+s3 hello
diff --git a/libs/libtpl-1.5/tests/test95.c b/libs/libtpl-1.5/tests/test95.c
new file mode 100755 (executable)
index 0000000..d7b0f6d
--- /dev/null
@@ -0,0 +1,23 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename="/tmp/test95.tpl";
+int main() {
+  tpl_node *tn;
+  char *s1 = NULL, *s2 = "", *s3 = "hello";
+  tn = tpl_map("sss", &s1, &s2, &s3);
+  tpl_pack(tn,0);
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  s1 = s2 = s3 = (char*)0x1; /* overwritten below */
+  tn  = tpl_map("sss", &s1, &s2, &s3);
+  tpl_load(tn,TPL_FILE,filename);
+  tpl_unpack(tn,0);
+  tpl_free(tn);
+  printf("s1 %s\n", s1?s1:"NULL");
+  printf("s2 %s\n", s2?s2:"NULL");
+  printf("s3 %s\n", s3?s3:"NULL");
+  return(0);
+}
+
diff --git a/libs/libtpl-1.5/tests/test95.out b/libs/libtpl-1.5/tests/test95.out
new file mode 100644 (file)
index 0000000..9ce4720
--- /dev/null
@@ -0,0 +1,3 @@
+s1 NULL
+s2 
+s3 hello
diff --git a/libs/libtpl-1.5/tests/test96 b/libs/libtpl-1.5/tests/test96
new file mode 100755 (executable)
index 0000000..b336b84
Binary files /dev/null and b/libs/libtpl-1.5/tests/test96 differ
diff --git a/libs/libtpl-1.5/tests/test96.ans b/libs/libtpl-1.5/tests/test96.ans
new file mode 100755 (executable)
index 0000000..6f463a1
--- /dev/null
@@ -0,0 +1,15 @@
+s1 NULL
+s2 
+s3 hello
+s1 NULL
+s2 
+s3 hello
+s1 NULL
+s2 
+s3 hello
+s1 NULL
+s2 
+s3 hello
+s1 NULL
+s2 
+s3 hello
diff --git a/libs/libtpl-1.5/tests/test96.c b/libs/libtpl-1.5/tests/test96.c
new file mode 100755 (executable)
index 0000000..8e45bef
--- /dev/null
@@ -0,0 +1,27 @@
+#include "tpl.h"
+#include <stdio.h>
+
+const char *filename="/tmp/test96.tpl";
+int main() {
+  tpl_node *tn;
+  int i;
+  char *s1 = NULL, *s2 = "", *s3 = "hello";
+  tn = tpl_map("A(sss)", &s1, &s2, &s3);
+  for(i=0;i<5;i++) {
+    tpl_pack(tn,1);
+  }
+  tpl_dump(tn,TPL_FILE,filename);
+  tpl_free(tn);
+
+  s1 = s2 = s3 = (char*)0x1; /* overwritten below */
+  tn  = tpl_map("A(sss)", &s1, &s2, &s3);
+  tpl_load(tn,TPL_FILE,filename);
+  while( tpl_unpack(tn,1) > 0) {
+    printf("s1 %s\n", s1?s1:"NULL");
+    printf("s2 %s\n", s2?s2:"NULL");
+    printf("s3 %s\n", s3?s3:"NULL");
+  }
+  tpl_free(tn);
+  return(0);
+}
+
diff --git a/libs/libtpl-1.5/tests/test96.out b/libs/libtpl-1.5/tests/test96.out
new file mode 100644 (file)
index 0000000..6f463a1
--- /dev/null
@@ -0,0 +1,15 @@
+s1 NULL
+s2 
+s3 hello
+s1 NULL
+s2 
+s3 hello
+s1 NULL
+s2 
+s3 hello
+s1 NULL
+s2 
+s3 hello
+s1 NULL
+s2 
+s3 hello
diff --git a/libs/libtpl-1.5/tests/test97 b/libs/libtpl-1.5/tests/test97
new file mode 100755 (executable)
index 0000000..962283d
Binary files /dev/null and b/libs/libtpl-1.5/tests/test97 differ
diff --git a/libs/libtpl-1.5/tests/test97.ans b/libs/libtpl-1.5/tests/test97.ans
new file mode 100755 (executable)
index 0000000..2fe2921
--- /dev/null
@@ -0,0 +1 @@
+j is -128, v is 65535
diff --git a/libs/libtpl-1.5/tests/test97.c b/libs/libtpl-1.5/tests/test97.c
new file mode 100755 (executable)
index 0000000..c1ed67b
--- /dev/null
@@ -0,0 +1,27 @@
+#include "tpl.h"
+#include <stdio.h>
+#include <inttypes.h>
+
+const char *filename = "/tmp/test97.tpl";
+
+int main() {
+   tpl_node *tn;
+   int16_t j = -128;
+   uint16_t v=65535;
+
+   tn = tpl_map("jv", &j, &v);
+   tpl_pack(tn,0);
+   tpl_dump(tn,TPL_FILE,filename);
+   tpl_free(tn);
+
+   j = v = 0;
+
+   tn = tpl_map("jv", &j, &v);
+   tpl_load(tn,TPL_FILE,filename);
+   tpl_unpack(tn,0);
+   tpl_free(tn);
+
+   printf("j is %d, v is %d\n", (int)j, (int)v);
+   return(0);
+   
+}
diff --git a/libs/libtpl-1.5/tests/test97.out b/libs/libtpl-1.5/tests/test97.out
new file mode 100644 (file)
index 0000000..2fe2921
--- /dev/null
@@ -0,0 +1 @@
+j is -128, v is 65535
diff --git a/libs/libtpl-1.5/tests/test98 b/libs/libtpl-1.5/tests/test98
new file mode 100755 (executable)
index 0000000..ed86027
Binary files /dev/null and b/libs/libtpl-1.5/tests/test98 differ
diff --git a/libs/libtpl-1.5/tests/test98.ans b/libs/libtpl-1.5/tests/test98.ans
new file mode 100755 (executable)
index 0000000..6a2a1cc
--- /dev/null
@@ -0,0 +1,3 @@
+j is -128, v is 65535
+j is -129, v is 65534
+j is -130, v is 65533
diff --git a/libs/libtpl-1.5/tests/test98.c b/libs/libtpl-1.5/tests/test98.c
new file mode 100755 (executable)
index 0000000..1eb9541
--- /dev/null
@@ -0,0 +1,28 @@
+#include "tpl.h"
+#include <stdio.h>
+#include <inttypes.h>
+
+const char *filename = "/tmp/test98.tpl";
+
+int main() {
+   tpl_node *tn;
+   int16_t j = -128;
+   uint16_t v=65535;
+
+   tn = tpl_map("A(jv)", &j, &v);
+   tpl_pack(tn,1); j -= 1; v-= 1;
+   tpl_pack(tn,1); j -= 1; v-= 1;
+   tpl_pack(tn,1); 
+   tpl_dump(tn,TPL_FILE,filename);
+   tpl_free(tn);
+
+   j = v = 0;
+
+   tn = tpl_map("A(jv)", &j, &v);
+   tpl_load(tn,TPL_FILE,filename);
+   while (tpl_unpack(tn,1) > 0) {
+     printf("j is %d, v is %d\n", (int)j, (int)v);
+   }
+   tpl_free(tn);
+   return(0);
+}
diff --git a/libs/libtpl-1.5/tests/test98.out b/libs/libtpl-1.5/tests/test98.out
new file mode 100644 (file)
index 0000000..6a2a1cc
--- /dev/null
@@ -0,0 +1,3 @@
+j is -128, v is 65535
+j is -129, v is 65534
+j is -130, v is 65533
diff --git a/libs/libtpl-1.5/tests/test99 b/libs/libtpl-1.5/tests/test99
new file mode 100755 (executable)
index 0000000..c4f065e
Binary files /dev/null and b/libs/libtpl-1.5/tests/test99 differ
diff --git a/libs/libtpl-1.5/tests/test99.ans b/libs/libtpl-1.5/tests/test99.ans
new file mode 100755 (executable)
index 0000000..3267dcf
--- /dev/null
@@ -0,0 +1,2 @@
+cA(i#)S(cf#)A(ci#)
+&
diff --git a/libs/libtpl-1.5/tests/test99.c b/libs/libtpl-1.5/tests/test99.c
new file mode 100755 (executable)
index 0000000..f4ac12a
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+
+int main() {
+    char *fmt, c;
+    fmt = tpl_peek(TPL_FILE|TPL_DATAPEEK, "test99.tpl", "c", &c);
+    if (fmt) {
+        printf("%s\n",fmt);
+        free(fmt);
+        printf("%c\n", c);
+    }
+    return 0;
+}
diff --git a/libs/libtpl-1.5/tests/test99.out b/libs/libtpl-1.5/tests/test99.out
new file mode 100644 (file)
index 0000000..3267dcf
--- /dev/null
@@ -0,0 +1,2 @@
+cA(i#)S(cf#)A(ci#)
+&
diff --git a/libs/libtpl-1.5/tests/test99.tpl b/libs/libtpl-1.5/tests/test99.tpl
new file mode 100755 (executable)
index 0000000..bb934e3
Binary files /dev/null and b/libs/libtpl-1.5/tests/test99.tpl differ
diff --git a/libs/libtpl-1.5/tests/threads/Makefile b/libs/libtpl-1.5/tests/threads/Makefile
new file mode 100755 (executable)
index 0000000..f44ca2e
--- /dev/null
@@ -0,0 +1,26 @@
+TPLSRC = ../../src
+PROGS = test1
+
+# Thread support requires compiler-specific options
+# ----------------------------------------------------------------------------
+# GNU 
+CFLAGS = -I$(TPLSRC) -g -pthread
+# Solaris (Studio 11 on Sparc Ultra3) 
+#CFLAGS = -I$(TPLSRC) -g -mt
+# ----------------------------------------------------------------------------
+
+all: $(PROGS) run_tests
+
+tpl.o :        $(TPLSRC)/tpl.c $(TPLSRC)/tpl.h
+       $(CC) -c $(CFLAGS) $(TPLSRC)/tpl.c
+
+$(PROGS) : tpl.o 
+       $(CC) $(CFLAGS) -o $@ $(@).c tpl.o
+
+run_tests: $(PROGS)
+       perl ../do_tests
+
+.PHONY: clean
+
+clean: 
+       rm -f $(PROGS) tpl.o test*.out
diff --git a/libs/libtpl-1.5/tests/threads/README b/libs/libtpl-1.5/tests/threads/README
new file mode 100755 (executable)
index 0000000..44f5e5c
--- /dev/null
@@ -0,0 +1,3 @@
+Tests for using tpl in threaded programs. 
+
+thread_ipc.c    a thread version of the pipe IPC test ../test28.c
diff --git a/libs/libtpl-1.5/tests/threads/test1.ans b/libs/libtpl-1.5/tests/threads/test1.ans
new file mode 100755 (executable)
index 0000000..5b92e81
--- /dev/null
@@ -0,0 +1,2 @@
+sum is 49995000
+thread result: 0 null
diff --git a/libs/libtpl-1.5/tests/threads/test1.c b/libs/libtpl-1.5/tests/threads/test1.c
new file mode 100755 (executable)
index 0000000..388021d
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tpl.h"
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+int fd[2];
+
+void *thread_routine( void *arg ) {
+    tpl_node *tn;
+    int i,sum=0;
+
+    /* child */
+    tn = tpl_map("A(u)",&i);
+    tpl_load(tn, TPL_FD, fd[0]);
+    while (tpl_unpack(tn,1) > 0) sum += i;
+    tpl_free(tn);
+    printf("sum is %d\n", sum);
+    return NULL;
+}
+
+int main() {
+    tpl_node *tn;
+    unsigned i;
+    int status;
+    pthread_t thread_id;
+    void *thread_result;
+
+    pipe(fd);
+    if ( status = pthread_create( &thread_id, NULL, thread_routine, NULL )) {
+        printf("failure: status %d\n", status);
+        exit(-1);
+    }
+    /* parent */
+    tn = tpl_map("A(u)",&i);
+    for(i=0;i<10000;i++) tpl_pack(tn,1);
+    tpl_dump(tn,TPL_FD, fd[1] );
+    tpl_free(tn);
+
+    status = pthread_join( thread_id, &thread_result );
+    printf("thread result: %d %s\n", status, thread_result ? "non-null":"null");
+}
index d8785d7baea1c4fcf737e3a859628431349a98a8..d8f95d8d288b7f40adcdcef79f6fa74065e1f5cb 100644 (file)
@@ -47,7 +47,7 @@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-4.0.2\libtiff;"\r
+                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-4.0.2\libtiff;libs\libtpl-1.5\src;libs\libtpl-1.5\src\win;"\r
                                PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;PCRE_STATIC;STATICLIB"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-4.0.2\libtiff;"\r
+                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-4.0.2\libtiff;libs\libtpl-1.5\src;libs\libtpl-1.5\src\win;"\r
                                PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;PCRE_STATIC;STATICLIB"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-4.0.2\libtiff;"\r
+                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-4.0.2\libtiff;libs\libtpl-1.5\src;libs\libtpl-1.5\src\win;"\r
                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;STATICLIB;CRASH_PROT;PCRE_STATIC"\r
                                RuntimeLibrary="2"\r
                                UsePrecompiledHeader="2"\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-4.0.2\libtiff;"\r
+                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;..\..\libs\spandsp\src\msvc;..\..\libs\spandsp\src;..\..\libs\tiff-4.0.2\libtiff;libs\libtpl-1.5\src;libs\libtpl-1.5\src\win;"\r
                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;STATICLIB;CRASH_PROT;PCRE_STATIC"\r
                                RuntimeLibrary="2"\r
                                UsePrecompiledHeader="2"\r
                                        />\r
                                </FileConfiguration>\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\libs\libtpl-1.5\src\tpl.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\libs\libtpl-1.5\src\win\mmap.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Debug|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|x64"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\src\switch_apr.c"\r
                                >\r
                                RelativePath="..\..\libs\stfu\stfu.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\libs\libtpl-1.5\src\tpl.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\libs\libtpl-1.5\src\win\mman.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\src\include\switch.h"\r
                                >\r
index 604d773fe16b59820a70cdb5a0182e1f798f3f4f..52e54064571f50b1908556a2a7cfc46e1c55c3c6 100644 (file)
@@ -43,7 +43,7 @@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include"\r
+                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;libs\libtpl-1.5\src;libs\libtpl-1.5\src\win;"\r
                                PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;PCRE_STATIC;STATICLIB"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include"\r
+                               AdditionalIncludeDirectories="..\..\src\include;..\..\libs\include;..\..\libs\srtp\include;..\..\libs\srtp\crypto\include;..\..\libs\libteletone\src;..\..\libs\win32\sqlite;..\..\libs\pcre;..\..\libs\stfu;..\..\libs\speex\include;libs\libtpl-1.5\src;libs\libtpl-1.5\src\win;"\r
                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FREESWITCHCORE_EXPORTS;STATICLIB;CRASH_PROT;PCRE_STATIC"\r
                                RuntimeLibrary="2"\r
                                UsePrecompiledHeader="2"\r
                                        />\r
                                </FileConfiguration>\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\libs\libtpl-1.5\src\tpl.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\libs\libtpl-1.5\src\win\mmap.c"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                               <FileConfiguration\r
+                                       Name="Release|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               UsePrecompiledHeader="0"\r
+                                               PrecompiledHeaderThrough=""\r
+                                               PrecompiledHeaderFile=""\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\src\switch_apr.c"\r
                                >\r
                                RelativePath="..\..\libs\stfu\stfu.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\libs\libtpl-1.5\src\tpl.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\libs\libtpl-1.5\src\win\mman.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\src\include\switch.h"\r
                                >\r