initial import

This commit is contained in:
Troy D. Hanson 2013-03-12 16:38:58 -04:00
parent f07a15b3cf
commit feec3bb950
405 changed files with 16806 additions and 0 deletions

21
LICENSE Executable file
View File

@ -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.

2
Makefile.am Normal file
View File

@ -0,0 +1,2 @@
SUBDIRS = src
EXTRA_DIST = LICENSE tests lang doc

56
README Normal file
View File

@ -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

11
bootstrap Executable file
View File

@ -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

28
configure.ac Normal file
View File

@ -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

26
doc/Makefile Normal file
View File

@ -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 -f 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

11
doc/NOTES Normal file
View File

@ -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

796
doc/html/ChangeLog.html Normal file
View File

@ -0,0 +1,796 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="generator" content="AsciiDoc 8.5.2" />
<title>tpl ChangeLog</title>
<style type="text/css">
/* 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;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
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;
}
ul, ol, li > p {
margin-top: 0;
}
pre {
padding: 0;
margin: 0;
}
span#author {
color: #527bbd;
font-family: sans-serif;
font-weight: bold;
font-size: 1.1em;
}
span#email {
}
span#revnumber, span#revdate, span#revremark {
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 {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
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 > div.content {
border: 1px solid silver;
background: #f4f4f4;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #dddddd;
color: #777777;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > div.content {
white-space: pre;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
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: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-family: sans-serif;
font-weight: bold;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
@media print {
div#footer-badges { display: none; }
}
div#toc {
margin-bottom: 2.5em;
}
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;
}
/* 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 {
color: #527bbd;
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-attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock-content {
white-space: pre;
}
div.verseblock-attribution {
padding-top: 0.75em;
text-align: left;
}
div.exampleblock-content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
/* IE6 sets dynamically generated links as visited. */
div#toc a:visited { color: blue; }
</style>
<script type="text/javascript">
/*<![CDATA[*/
window.onload = function(){asciidoc.footnotes();}
var asciidoc = { // Namespace.
/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////
/* 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 */
/* modified by Stuart Rackham, 2006, 2009. License: GPL */
// toclevels = 1..4.
toc: function (toclevels) {
function 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 += getText(i);
}
return text;
}
function TocEntry(el, text, toclevel) {
this.element = el;
this.text = text;
this.toclevel = toclevel;
}
function tocEntries(el, toclevels) {
var result = new Array;
var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
// Function that scans the DOM tree for header elements (the DOM2
// nodeIterator API would be a better technique but not supported by all
// browsers).
var iterate = function (el) {
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
var mo = re.exec(i.tagName);
if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
}
iterate(i);
}
}
}
iterate(el);
return result;
}
var toc = document.getElementById("toc");
var entries = tocEntries(document.getElementById("content"), toclevels);
for (var i = 0; i < entries.length; ++i) {
var entry = entries[i];
if (entry.element.id == "")
entry.element.id = "_toc_" + i;
var a = document.createElement("a");
a.href = "#" + entry.element.id;
a.appendChild(document.createTextNode(entry.text));
var div = document.createElement("div");
div.appendChild(a);
div.className = "toclevel" + entry.toclevel;
toc.appendChild(div);
}
if (entries.length == 0)
toc.parentNode.removeChild(toc);
},
/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////
/* Based on footnote generation code from:
* http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
*/
footnotes: function () {
var cont = document.getElementById("content");
var noteholder = document.getElementById("footnotes");
var spans = cont.getElementsByTagName("span");
var refs = {};
var n = 0;
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnote") {
n++;
// Use [\s\S] in place of . so multi-line matches work.
// Because JavaScript has no s (dotall) regex flag.
note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
noteholder.innerHTML +=
"<div class='footnote' id='_footnote_" + n + "'>" +
"<a href='#_footnoteref_" + n + "' title='Return to text'>" +
n + "</a>. " + note + "</div>";
spans[i].innerHTML =
"[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
var id =spans[i].getAttribute("id");
if (id != null) refs["#"+id] = n;
}
}
if (n == 0)
noteholder.parentNode.removeChild(noteholder);
else {
// Process footnoterefs.
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnoteref") {
var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
href = href.match(/#.*/)[0]; // Because IE return full URL.
n = refs[href];
spans[i].innerHTML =
"[<a href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
}
}
}
}
}
/*]]>*/
</script>
</head>
<body>
<div id="header">
<h1>tpl ChangeLog</h1>
</div>
<div id="content">
<h2 id="_version_1_6_2010">Version 1.6 (2010-??-??)</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
Fixed a bug in the Windows version of tpl that prevented an application
from serializing more than once to the same file- the file stayed locked until
the application was closed. (thanks, Werner Krattenthaler!)
</p>
</li>
<li>
<p>
Fixed a documentation error to indicate that <tt>tpl_dump</tt> when used in the
<tt>TPL_GETSIZE</tt> mode stores its result in a <tt>size_t</tt> rather than a <tt>uint32_t</tt>
(thanks, M. Nunberge!)
</p>
</li>
<li>
<p>
Fixed a typo in the User Guide example of packing a linked link (thanks, Bryan Mishkin!)
</p>
</li>
</ul></div>
</div>
<h2 id="_version_1_5_2010_02_05">Version 1.5 (2010-02-05)</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
tpl now builds as a DLL under Microsoft Visual Studio! (thanks, degski and Zhang Yafei!)
</p>
</li>
<li>
<p>
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>
</p>
</li>
<li>
<p>
a crash in <tt>tpl_free</tt> on certain format strings has been fixed (thanks, Eric Rose!)
</p>
</li>
<li>
<p>
fixed a bug in <tt>tpl_dump</tt> on 64-bit, big-endian platforms
</p>
</li>
<li>
<p>
changed some pointer casts from <tt>long</tt> to <tt>uintptr_t</tt> since 64-bit Windows has 32-bit longs
</p>
</li>
<li>
<p>
tpl has been downloaded 4,195 times.
</p>
</li>
</ul></div>
</div>
<h2 id="_version_1_4_2009_04_21">Version 1.4 (2009-04-21)</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
fixed-length arrays can now be multi-dimensional like <tt>i##</tt>
</p>
</li>
<li>
<p>
fixed-length string arrays like <tt>s#</tt> are now supported
</p>
</li>
<li>
<p>
nested structures can now be expressed, using the dollar symbol, e.g. <tt>S(ci$(cc))</tt>
</p>
</li>
<li>
<p>
<tt>tpl_dump</tt> can use a caller-allocated output buffer (<tt>TPL_MEM|TPL_PREALLOCD</tt>)
</p>
</li>
<li>
<p>
<tt>tpl_load</tt> can tolerate excess space in input buffer (<tt>TPL_MEM|TPL_EXCESS_OK</tt>)
</p>
</li>
<li>
<p>
implement <tt>TPL_FXLENS</tt> flag for <tt>tpl_peek</tt> to get lengths of fixed-length arrays
</p>
</li>
<li>
<p>
implement <tt>TPL_GETSIZE</tt> flag for <tt>tpl_dump</tt> to get dump size without dumping
</p>
</li>
<li>
<p>
fix success return code from <tt>tpl_dump(TPL_FD,...)</tt> (thanks, Max Lapan!)
</p>
</li>
<li>
<p>
deprecated the wildcard unpacking <tt>S(*)</tt> feature
</p>
</li>
</ul></div>
</div>
<h2 id="_version_1_3_2009_02_10">Version 1.3 (2009-02-10)</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
added <tt>TPL_DATAPEEK</tt> mode for <tt>tpl_peek</tt>
</p>
</li>
<li>
<p>
added support for <tt>NULL</tt> strings
</p>
</li>
<li>
<p>
added support for 16-bit integer types (<tt>j</tt>,<tt>v</tt>)
</p>
</li>
<li>
<p>
added <tt>tpl_jot</tt>
</p>
</li>
<li>
<p>
added support for fixed-length arrays of structures <tt>S(...)#</tt>
</p>
</li>
<li>
<p>
added support for pre-C99 compilers (thanks, Wei Wei!)
</p>
</li>
<li>
<p>
improved structure alignment calculation (thanks, Wu Yongwei!)
</p>
</li>
<li>
<p>
added RPM spec file (thanks, Alessandro Ren!)
</p>
</li>
<li>
<p>
compiles cleanly with <tt>-Wall</tt> and <tt>-pedantic</tt> and with <tt>-O3</tt>
</p>
</li>
<li>
<p>
made <a href="license.html">BSD license</a> terms even more permissive
</p>
</li>
<li>
<p>
test suite: exit with status zero when all tests pass
</p>
</li>
<li>
<p>
added PDF user guide
</p>
</li>
<li>
<p>
added <a href="http://troydhanson.wordpress.com/feed/">update news</a> <span class="image">
<img src="img/rss.png" alt="(RSS)" />
</span>
</p>
</li>
<li>
<p>
added <a href="http://apps.sourceforge.net/mediawiki/tpl/">tpl wiki</a>
</p>
</li>
</ul></div>
</div>
<h2 id="_version_1_2_2007_04_27">Version 1.2 (2007-04-27)</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
Perl API and XML converter support 64-bit types
</p>
</li>
</ul></div>
</div>
<h2 id="_version_1_1_2007_04_25">Version 1.1 (2007-04-25)</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
support for serializing C structures
</p>
</li>
<li>
<p>
support for serializing fixed-length arrays
</p>
</li>
<li>
<p>
MinGW support (thanks, Horea Haitonic!)
</p>
</li>
<li>
<p>
revised User Guide
</p>
</li>
</ul></div>
</div>
<h2 id="_version_1_0_2006_09_28">Version 1.0 (2006-09-28)</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
Initial version
</p>
</li>
</ul></div>
</div>
</div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Last updated 2011-04-27 22:45:54 EDT
</div>
</div>
</body>
</html>

BIN
doc/html/img/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

429
doc/html/img/banner.svg Normal file
View File

@ -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>

After

Width:  |  Height:  |  Size: 17 KiB

BIN
doc/html/img/grad_azure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

105
doc/html/img/grad_azure.svg Normal file
View File

@ -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>

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
doc/html/img/rss.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

BIN
doc/html/img/tpl-mini.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

242
doc/html/img/tpl-mini.svg Normal file
View File

@ -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>

After

Width:  |  Height:  |  Size: 12 KiB

BIN
doc/html/img/tpl.dia Normal file

Binary file not shown.

BIN
doc/html/img/tpl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
doc/html/img/tpl_aai.dia Normal file

Binary file not shown.

162
doc/html/index.html Normal file
View File

@ -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>

61
doc/html/license.html Normal file
View File

@ -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>

412
doc/html/perl.html Normal file
View File

@ -0,0 +1,412 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="generator" content="AsciiDoc 8.5.2" />
<title>tpl Perl API</title>
<link rel="stylesheet" href="./tdh.css" type="text/css" />
<link rel="stylesheet" href="./tdh-quirks.css" type="text/css" />
<script type="text/javascript">
/*<![CDATA[*/
window.onload = function(){asciidoc.footnotes();}
/*]]>*/
</script>
<script type="text/javascript" src="./asciidoc-xhtml11.js"></script>
</head>
<body>
<div id="header">
<h1>tpl Perl API</h1>
<span id="author">Troy D. Hanson</span><br />
<span id="email"><tt>&lt;<a href="mailto:troydhanson@comcast.net">troydhanson@comcast.net</a>&gt;</tt></span><br />
<span id="revnumber">version 1.1,</span>
<span id="revdate">April 2007</span>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<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>
<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;
tpl Perl API
<a style="padding: 8px;" href="userguide.pdf">[View PDF]</a>
</div>
</div>
</div>
<h2 id="_perl_api">Perl API</h2>
<div class="sectionbody">
<div id="toc"></div>
<script>
window.onload=generate_TOC
/* Author: Mihai Bazon, September 2002
* <a href="http://students.infoiasi.ro/~mishoo">http://students.infoiasi.ro/~mishoo</a>
*
* 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>
<div class="paragraph"><p>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.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
<div class="title">Start with the C API</div>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
<a href="userguide.html">User Guide</a>.</td>
</tr></table>
</div>
<h3 id="_tpl_pm">Tpl.pm</h3><div style="clear:left"></div>
<div class="paragraph"><p>The <tt>Tpl.pm</tt> file (in the <tt>lang/perl</tt>) directory contains the Perl module. You
can copy it to another directory if you wish. Your Perl program may need to
include a <tt>use lib</tt> statement to find the module.</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>#!/usr/bin/perl
use lib "/some/directory";
use Tpl;</tt></pre>
</div></div>
<h3 id="_tpl_map">tpl_map</h3><div style="clear:left"></div>
<div class="paragraph"><p>This function resembles the C version, except that it&#8217;s invoked via the <tt>Tpl</tt>
module, and it takes references to Perl variables after the format string.</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>my $i;
my $tpl = Tpl-&gt;tpl_map("A(i)",\$i);</tt></pre>
</div></div>
<div class="paragraph"><p>The return value is a tpl object; all other API calls are object methods.
Incidentally, there is no <tt>tpl_free()</tt> method corresponding to the C API.</p></div>
<h4 id="_fixed_length_arrays">Fixed-length arrays</h4>
<div class="paragraph"><p>Format strings such as <tt>i#</tt> denote a fixed-length array. In the Perl API,
fixed-length arrays require two arguments: a list reference, and the fixed
length. For example:</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>my @x;
my $tpl = Tpl-&gt;tpl_map("i#", \@x, 10);</tt></pre>
</div></div>
<div class="paragraph"><p>When fixed-length arrays are packed or unpacked, the specified number of
elements will be copied from (or placed into) the designated list.</p></div>
<h4 id="_structures">Structures</h4>
<div class="paragraph"><p>Format strings containing <tt>S(...)</tt> 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 <tt>S(...)</tt> and consider only its interior format characters when
constructing the argument list:</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>my ($str, $int);
my $tpl = Tpl-&gt;tpl_map("S(si)", \$str, \$int);</tt></pre>
</div></div>
<div class="paragraph"><p>It really only makes sense to use <tt>S(...)</tt> in a format string in the Perl API if
you are communicating with a C program that uses structures.</p></div>
<h3 id="_tpl_pack">tpl_pack</h3><div style="clear:left"></div>
<div class="paragraph"><p>This is nearly identical to the C version. The only argument is the index
number to pack.</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>$tpl-&gt;tpl_pack(1);</tt></pre>
</div></div>
<h3 id="_tpl_dump">tpl_dump</h3><div style="clear:left"></div>
<div class="paragraph"><p>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.</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>$tpl-&gt;tpl_dump("demo.tpl"); # writes demo.tpl</tt></pre>
</div></div>
<div class="paragraph"><p>Or,</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>my $img = $tpl-&gt;tpl_dump();</tt></pre>
</div></div>
<div class="paragraph"><p>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 <tt>tpl_load()</tt>.</p></div>
<h3 id="_tpl_load">tpl_load</h3><div style="clear:left"></div>
<div class="paragraph"><p>This method loads a tpl image from a file or from a Perl variable. It takes
one argument. If it&#8217;s not a reference, it&#8217;s assumed to be a filename to load.</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>$tpl-&gt;tpl_load("demo.tpl");</tt></pre>
</div></div>
<div class="paragraph"><p>Otherwise, if the argument is a Perl reference, it&#8217;s construed as a variable
containing the tpl image:</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>$tpl-&gt;tpl_load(\$img);</tt></pre>
</div></div>
<div class="paragraph"><p>The method will <tt>die</tt> if the image is invalid or the file doesn&#8217;t exist. You
can wrap it with <tt>eval</tt> to catch such errors:</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>eval { $tpl-&gt;tpl_load(\$img); };
print "failed to load\n" if $@;</tt></pre>
</div></div>
<h3 id="_tpl_unpack">tpl_unpack</h3><div style="clear:left"></div>
<div class="paragraph"><p>This is nearly identical to the C version. The only argument is the index
number to unpack.</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>$tpl-&gt;tpl_unpack(1);</tt></pre>
</div></div>
</div>
<h2 id="_examples">Examples</h2>
<div class="sectionbody">
<h3 id="_integer_array">Integer array</h3><div style="clear:left"></div>
<div class="listingblock">
<div class="title">Packing A(i) to file</div>
<div class="content">
<pre><tt>#!/usr/bin/perl
use strict;
use warnings;
use Tpl;
my $i;
my $tpl = Tpl-&gt;tpl_map("A(i)",\$i);
for($i=0; $i&lt;10; $i++) {
$tpl-&gt;tpl_pack(1);
}
$tpl-&gt;tpl_dump("demo.tpl");</tt></pre>
</div></div>
<div class="listingblock">
<div class="title">Unpacking A(i) from file</div>
<div class="content">
<pre><tt>#!/usr/bin/perl
use strict;
use warnings;
use Tpl;
my $j;
my $tpl2 = Tpl-&gt;tpl_map("A(i)",\$j);
$tpl2-&gt;tpl_load("demo.tpl");
while($tpl2-&gt;tpl_unpack(1) &gt; 0) {
print "$j\n";
}</tt></pre>
</div></div>
<h3 id="_message_passing">Message-passing</h3><div style="clear:left"></div>
<div class="paragraph"><p>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&#8217;ll code both a client
and a server in Perl.</p></div>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title">A server that sums integers</div>
<div class="paragraph"><p>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.</p></div>
</div></div>
<h4 id="_server">Server</h4>
<div class="paragraph"><p>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.</p></div>
<div class="paragraph"><p>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.</p></div>
<div class="listingblock">
<div class="title">Server</div>
<div class="content">
<pre><tt>#!/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 = &lt;$client&gt;; # get request (slurp)
# read input array, and calculate total
my ($i,$total);
my $tpl = Tpl-&gt;tpl_map("A(i)", \$i);
eval { $tpl-&gt;tpl_load(\$request); };
die "received invalid tpl" if $@;
$total += $i while $tpl-&gt;tpl_unpack(1) &gt; 0;
# formulate response and send
my $tpl2 = Tpl-&gt;tpl_map("i", \$total);
$tpl2-&gt;tpl_pack(0);
my $response = $tpl2-&gt;tpl_dump();
print $client $response;
close $client;
}
my $server = IO::Socket::INET-&gt;new(LocalPort =&gt; $port,
Type =&gt; SOCK_STREAM,
Reuse =&gt; 1,
Listen =&gt; 10 )
or die "Can't listen on port $port: $!\n";
while (1) {
my $client = $server-&gt;accept();
next unless $client;
# new connection
my $pid = fork;
die "can't fork: $!\n" unless defined $pid;
if ($pid &gt; 0) {
# parent
close $client;
} elsif ($pid == 0) {
# child
handle_client($client);
exit(0);
}
}
close ($server);</tt></pre>
</div></div>
<h4 id="_client">Client</h4>
<div class="paragraph"><p>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.</p></div>
<div class="listingblock">
<div class="title">Client</div>
<div class="content">
<pre><tt>#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket::INET;
use Tpl;
our $port = 2000;
# construct tpl
my $i;
my $tpl = Tpl-&gt;tpl_map("A(i)",\$i);
$tpl-&gt;tpl_pack(1) while ($i=shift @ARGV);
my $request = $tpl-&gt;tpl_dump();
# send to server, get response
my $socket = IO::Socket::INET-&gt;new("localhost:$port") or die "can't connect";
print $socket $request;
shutdown($socket,1); # done writing (half-close)
undef $/;
my $response = &lt;$socket&gt;; # get reply (slurp)
# decode response (or print error)
my $total;
my $tpl2 = Tpl-&gt;tpl_map("i", \$total);
eval { $tpl2-&gt;tpl_load(\$response); };
die "invalid response\n" if $@;
$tpl2-&gt;tpl_unpack(0);
print "total is $total\n";</tt></pre>
</div></div>
<h4 id="_running_thise_example">Running thise example</h4>
<div class="paragraph"><p>If the client and server programs are in <tt>client.pl</tt> and <tt>server.pl</tt>, then
you can run the example by starting the server in one window:</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>./server.pl</tt></pre>
</div></div>
<div class="paragraph"><p>Then run the client in another window. E.g.,</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>./client.pl 1 2 3 4 5</tt></pre>
</div></div>
<div class="paragraph"><p>The client runs and then exits, printing:</p></div>
<div class="literalblock">
<div class="content">
<pre><tt>total is 15</tt></pre>
</div></div>
<div class="paragraph"><p>You can re-run the client with different arguments. When done, type <tt>Ctrl-C</tt> in
the server window to terminate it.</p></div>
</div>
</div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Version 1.1<br />
Last updated 2010-07-18 21:14:17 EDT
</div>
</div>
</body>
</html>

160
doc/html/styles.css Normal file
View File

@ -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;
}

41
doc/html/tdh-quirks.css Normal file
View File

@ -0,0 +1,41 @@
/* 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 {
color: #527bbd;
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-attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock-content {
white-space: pre;
}
div.verseblock-attribution {
padding-top: 0.75em;
text-align: left;
}
div.exampleblock-content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
/* IE6 sets dynamically generated links as visited. */
div#toc a:visited { color: blue; }

402
doc/html/tdh.css Normal file
View File

@ -0,0 +1,402 @@
/* 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;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
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;
}
ul, ol, li > p {
margin-top: 0;
}
pre {
padding: 0;
margin: 0;
}
span#author {
color: #527bbd;
font-family: sans-serif;
font-weight: bold;
font-size: 1.1em;
}
span#email {
}
span#revnumber, span#revdate, span#revremark {
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 {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
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 > div.content {
border: 1px solid silver;
background: #f4f4f4;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #dddddd;
color: #777777;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > div.content {
white-space: pre;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
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: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-family: sans-serif;
font-weight: bold;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
@media print {
div#footer-badges { display: none; }
}
div#toc {
margin-bottom: 2.5em;
}
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}

35
doc/html/toc.css Normal file
View File

@ -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}

1548
doc/html/userguide.html Normal file

File diff suppressed because it is too large Load Diff

BIN
doc/pdf/userguide.pdf Normal file

Binary file not shown.

70
doc/txt/ChangeLog.txt Normal file
View File

@ -0,0 +1,70 @@
tpl ChangeLog
=============
Version 1.6 (2011-??-??)
--------------------------
* Added `const` to a number of API parameters and exposed tpl_map_va (thanks, Simon Dawson!)
* Fixed a bug in the Windows version of tpl that prevented an application
from serializing more than once to the same file- the file stayed locked until
the application was closed. (thanks, Werner Krattenthaler!)
* Fixed a documentation error to indicate that `tpl_dump` when used in the
`TPL_GETSIZE` mode stores its result in a `size_t` rather than a `uint32_t`
(thanks, M. Nunberge!)
* Fixed a typo in the User Guide example of packing a linked link (thanks, Bryan Mishkin!)
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:

38
doc/txt/compiling.txt Normal file
View File

@ -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`.

297
doc/txt/examples.txt Normal file
View File

@ -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`.

52
doc/txt/future.txt Normal file
View File

@ -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]}

302
doc/txt/perl.txt Normal file
View File

@ -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:

5
doc/txt/sflogo.txt Normal file
View File

@ -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[]

85
doc/txt/toc.txt Normal file
View File

@ -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[]

10
doc/txt/topnav.txt Normal file
View File

@ -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[]

1264
doc/txt/userguide.txt Normal file

File diff suppressed because it is too large Load Diff

475
lang/perl/Tpl.pm Normal file
View File

@ -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

9
lang/perl/tests/Makefile Normal file
View File

@ -0,0 +1,9 @@
all: run_tests
run_tests:
perl ./do_tests
.PHONY: clean
clean:
rm -f test*.out

29
lang/perl/tests/README Normal file
View File

@ -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)

31
lang/perl/tests/client.pl Executable file
View File

@ -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";

20
lang/perl/tests/do_tests Executable file
View File

@ -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";

56
lang/perl/tests/server.pl Executable file
View File

@ -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);

23
lang/perl/tests/test1 Executable file
View File

@ -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" }

10
lang/perl/tests/test1.ans Normal file
View File

@ -0,0 +1,10 @@
0
1
2
3
4
5
6
7
8
9

16
lang/perl/tests/test10 Executable file
View File

@ -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;

View File

@ -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>

24
lang/perl/tests/test11 Executable file
View File

@ -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";

View File

@ -0,0 +1,2 @@

23
lang/perl/tests/test12 Executable file
View File

@ -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); }

View File

@ -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

16
lang/perl/tests/test13 Executable file
View File

@ -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;

View File

@ -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>

17
lang/perl/tests/test14 Executable file
View File

@ -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";

View File

@ -0,0 +1 @@
-2

BIN
lang/perl/tests/test14.tpl Normal file

Binary file not shown.

17
lang/perl/tests/test15 Executable file
View File

@ -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";

View File

@ -0,0 +1 @@
-3

BIN
lang/perl/tests/test15.tpl Normal file

Binary file not shown.

22
lang/perl/tests/test16 Executable file
View File

@ -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";

View File

@ -0,0 +1,2 @@

25
lang/perl/tests/test17 Executable file
View File

@ -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";

View File

@ -0,0 +1 @@
1,a

23
lang/perl/tests/test18 Executable file
View File

@ -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;

View File

@ -0,0 +1,3 @@
1
2
3

25
lang/perl/tests/test19 Executable file
View File

@ -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;

View File

@ -0,0 +1,7 @@
1
2
3
-1
-2
-3
-4

18
lang/perl/tests/test2 Executable file
View File

@ -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" }

10
lang/perl/tests/test2.ans Normal file
View File

@ -0,0 +1,10 @@
0
1
2
3
4
5
6
7
8
9

36
lang/perl/tests/test20 Executable file
View File

@ -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";

View File

@ -0,0 +1 @@
tpl files identical

15
lang/perl/tests/test21 Executable file
View File

@ -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");

View File

@ -0,0 +1 @@
A(i)

21
lang/perl/tests/test22 Executable file
View File

@ -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";

View File

@ -0,0 +1 @@
i#i#

21
lang/perl/tests/test23 Executable file
View File

@ -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";

16
lang/perl/tests/test3 Executable file
View File

@ -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;

53
lang/perl/tests/test3.ans Normal file
View File

@ -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>

26
lang/perl/tests/test4 Executable file
View File

@ -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";

View File

@ -0,0 +1 @@
tpl files identical

23
lang/perl/tests/test5 Executable file
View File

@ -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); }

10
lang/perl/tests/test5.ans Normal file
View File

@ -0,0 +1,10 @@
0
1
2
3
4
5
6
7
8
9

16
lang/perl/tests/test6 Executable file
View File

@ -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;

53
lang/perl/tests/test6.ans Normal file
View File

@ -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>

26
lang/perl/tests/test7 Executable file
View File

@ -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";

View File

@ -0,0 +1 @@
tpl files identical

29
lang/perl/tests/test8 Executable file
View File

@ -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";

View File

@ -0,0 +1 @@
tpl files identical

23
lang/perl/tests/test9 Executable file
View File

@ -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" }

10
lang/perl/tests/test9.ans Normal file
View File

@ -0,0 +1,10 @@
0
1
2
3
4
5
6
7
8
9

24
lang/perl/tplfmt Executable file
View File

@ -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;
}

306
lang/perl/tplxml Executable file
View File

@ -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";

7
src/Makefile.am Normal file
View File

@ -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

2478
src/tpl.c Normal file

File diff suppressed because it is too large Load Diff

137
src/tpl.h Normal file
View File

@ -0,0 +1,137 @@
/*
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 */
#include <stdarg.h> /* va_list */
#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)(const 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 */
TPL_API tpl_node *tpl_map_va(char *fmt, va_list ap);
#if defined __cplusplus
}
#endif
#endif /* TPL_H */

4
src/win/Makefile.am Normal file
View File

@ -0,0 +1,4 @@
noinst_LTLIBRARIES = libwinmmap.la
noinst_HEADERS = mman.h
libwinmmap_la_SOURCES = nonempty.c
libwinmmap_la_LIBADD = @LTLIBOBJS@

11
src/win/README Normal file
View File

@ -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

52
src/win/mman.h Normal file
View File

@ -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_ */

171
src/win/mmap.c Normal file
View File

@ -0,0 +1,171 @@
#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;
}
CloseHandle(h); /* ok to call UnmapViewOfFile after this */
/* 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;
}

6
src/win/nonempty.c Normal file
View File

@ -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;
}

88
tests/Makefile Normal file
View File

@ -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

Some files were not shown because too many files have changed in this diff Show More