aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbarenblat@galois.com>2014-01-13 15:56:57 -0800
committerGravatar Benjamin Barenblat <bbarenblat@galois.com>2014-01-13 15:56:57 -0800
commitb69ec3f6d953e67422dd32b72688cba850fd1b2e (patch)
treea24e664807c19bd3b50f504ce0d33df24f135a23
Initial commit
-rw-r--r--.dir-locals.el40
-rw-r--r--.gitignore56
-rw-r--r--COPYING674
-rw-r--r--Doxyfile40
-rw-r--r--INSTALL332
-rw-r--r--Makefile.am50
-rw-r--r--Makefile_doxygen.am164
-rw-r--r--README24
-rw-r--r--bindings/haskell/.gitignore7
-rw-r--r--bindings/haskell/README8
-rw-r--r--bindings/haskell/Setup.hs22
-rw-r--r--bindings/haskell/examples/simple.hs46
-rw-r--r--bindings/haskell/ppamltracer.cabal62
-rw-r--r--bindings/haskell/src/PPAML/Tracer.hs268
-rw-r--r--bindings/haskell/src/PPAML/Tracer/Exception.hs78
-rw-r--r--bindings/java/.gitignore7
-rw-r--r--bindings/java/README12
-rw-r--r--bindings/java/build.xml165
-rw-r--r--bindings/java/examples/build.xml41
-rw-r--r--bindings/java/examples/src/com/galois/ppaml/tracer/examples/Simple.java84
-rw-r--r--bindings/java/src/c/Makefile.am39
-rw-r--r--bindings/java/src/c/com_galois_ppaml_tracer_Phase.c97
-rw-r--r--bindings/java/src/c/com_galois_ppaml_tracer_Tracer.c76
-rw-r--r--bindings/java/src/c/configure.ac58
-rw-r--r--bindings/java/src/c/pointer.h38
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/CWrapper.java184
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/ClockAcquisitionException.java35
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/NativeOutOfMemoryError.java38
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFManagerException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFManagerInitializationException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterCloseException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterEntryException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterExitException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterInitializationException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterPhaseDefinitionException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterProcessDefinitionException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterResolutionException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/Phase.java220
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/TimingException.java34
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/Tracer.java163
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/UnexpectedReturnValueError.java37
-rw-r--r--bindings/java/src/java/com/galois/ppaml/tracer/package-info.java80
-rw-r--r--bindings/python/.gitignore8
-rw-r--r--bindings/python/MANIFEST.in21
-rw-r--r--bindings/python/README11
-rwxr-xr-xbindings/python/examples/simple.py49
-rw-r--r--bindings/python/ppamltracer.py365
-rwxr-xr-xbindings/python/setup.py34
-rw-r--r--bindings/racket/.gitignore16
-rw-r--r--bindings/racket/README11
-rw-r--r--bindings/racket/main.rkt396
-rw-r--r--bindings/racket/manual.scrbl181
-rw-r--r--configure.ac64
-rw-r--r--examples/simple.c92
-rw-r--r--include/Makefile.am23
-rw-r--r--include/ppaml/tracer.h166
-rw-r--r--include/ppaml/tracer/internal.h111
-rw-r--r--m4/ax_prog_doxygen.m4532
-rw-r--r--m4/otf.m474
-rw-r--r--ppamltracer.pc.in10
-rw-r--r--src/Makefile.am35
-rw-r--r--src/index.dox45
-rw-r--r--src/require.h46
-rw-r--r--src/timing.c86
-rw-r--r--src/timing.h32
-rw-r--r--src/tracer.c133
68 files changed, 6194 insertions, 0 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 0000000..ed52889
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,40 @@
+;; .dir-locals.el -- directory-local variables for ppamltracer
+;; Copyright (C) 2013 Galois, Inc.
+;;
+;; This library is free software: you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by the Free
+;; Software Foundation, either version 3 of the License, or (at your option)
+;; any later version.
+;;
+;; This library is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+;; more details.
+;;
+;; You should have received a copy of the GNU General Public License along with
+;; this library. If not, see <http://www.gnu.org/licenses/>.
+;;
+;; To contact Galois, complete the Web form at
+;; <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+;; 6th Avenue, Suite 300, Portland, Oregon, 97204-1622.
+
+((autoconf . ((fill-column . 80)
+ (indent-tabs-mode . nil)))
+ (c . ((c-file-style . "k&r")
+ (c-basic-offset . 8)
+ (fill-column . 80)
+ (tab-width . 8)
+ (indent-tabs-mode . t)))
+ (haskell-cabal-mode . ((fill-column . 80)
+ (indent-tabs-mode . nil)))
+ (haskell-mode . ((fill-column . 80)
+ (indent-tabs-mode . nil)))
+ (java-mode . ((fill-column . 80)
+ (indent-tabs-mode . nil)))
+ (python . (; as per PEP 8
+ (python-indent . 4)
+ (indent-tabs-mode . nil)
+ (fill-column . 79)))
+ (scheme-mode . ((indent-tabs-mode . nil)))
+ (scribble . ((indent-tabs-mode . nil)))
+ (nxml-mode . ((indent-tabs-mode . nil))))
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d4caf57
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,56 @@
+# .gitignore for ppamltracer -*- conf -*-
+
+# Editor backup files
+*~
+\#*
+.\#*
+
+# autoscan
+autoscan.log
+configure.scan
+
+# aclocal
+aclocal.m4
+autom4te.cache/
+m4/libtool.m4
+m4/lt*.m4
+
+# autoconf
+configure
+
+# autoheader
+config.h.in
+
+# libtoolize
+ltmain.sh
+
+# automake
+Makefile.in
+ar-lib
+config.guess
+config.sub
+depcomp
+install-sh
+missing
+
+# configure
+.deps/
+Makefile
+config.h
+config.log
+config.status
+libtool
+ppamltracer.pc
+stamp-*
+
+# make
+.libs/
+*.la
+*.lo
+*.o
+
+# Doxygen
+doc/
+
+# Examples
+examples/simple
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..fa1fec8
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,40 @@
+# Doxyfile -- Doxygen description for ppamltracer -*- conf -*-
+# Copyright (C) 2013 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+PROJECT_NAME = $(PROJECT)
+
+OUTPUT_DIRECTORY = $(DOCDIR)
+OPTIMIZE_OUTPUT_FOR_C = YES
+GENERATE_CHI = $(GENERATE_CHI)
+GENERATE_HTML = $(GENERATE_HTML)
+GENERATE_HTMLHELP = $(GENERATE_HTMLHELP)
+GENERATE_LATEX = $(GENERATE_LATEX)
+GENERATE_MAN = $(GENERATE_MAN)
+GENERATE_RTF = $(GENERATE_RTF)
+GENERATE_XML = $(GENERATE_XML)
+GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
+
+INPUT = $(SRCDIR)/src/index.dox $(SRCDIR)/include
+RECURSIVE = YES
+JAVADOC_AUTOBRIEF = YES
+ALPHABETICAL_INDEX = NO
+IGNORE_PREFIX = ppaml_
+
+EXAMPLE_PATH = $(SRCDIR)/examples
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..cc29059
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,332 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994-1996, 1999-2002, 2004-2012 Free Software Foundation, Inc.
+Copyright (C) 2013, 2014 Galois, Inc.
+
+Copying and distribution of this file, with or without modification, are
+permitted in any medium without royalty provided the copyright notice and this
+notice are preserved. This file is offered as-is, without warranty of any kind.
+
+Basic Installation
+==================
+
+Briefly, the shell commands
+
+ ./configure
+ make
+ make install
+
+should configure, build, and install this package.
+
+
+The `configure' shell script attempts to guess correct values for various
+system-dependent variables used during compilation. It uses those values to
+create a `Makefile' in the top-level directory of the package, as well as the
+`include' and `src' subdirectories. It also creates a `config.h' file
+containing system-dependent definitions. Finally, it creates a shell script
+`config.status' that you can run in the future to recreate the current
+configuration, and a file `config.log' containing compiler output (useful mainly
+for debugging `configure').
+
+It can also use an optional file (typically called `config.cache' and enabled
+with `--cache-file=config.cache' or simply `-C') that saves the results of its
+tests to speed up reconfiguring. Caching is disabled by default to prevent
+problems with accidental use of stale cache files.
+
+If you need to do unusual things to compile the package, please try to figure
+out how `configure' could check whether to do them, and mail diffs or
+instructions to the address given in the `README' so they can be considered for
+the next release. If you are using the cache, and at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+The file `configure.ac' is used to create `configure' by a program called
+`autoconf'. You need `configure.ac' if you want to change it or regenerate
+`configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. If you have not done so already, install the Open Trace Format development
+ libraries and the `otfconfig' program. Many GNU/Linux distributions
+ provide packages for libotf and otfconfig; if you need, however, you may
+ download the source from
+ <http://tu-dresden.de/die_tu_dresden/zentrale_einrichtungen/zih/forschung/projekte/otf>.
+
+ 2. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 3. Type `make' to compile the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular user,
+ and only the `make install' phase executed with root privileges.
+
+ 5. You can remove the program binaries and object files from the source code
+ directory by typing `make clean'. To also remove the files that
+ `configure' created (so you can compile the package for a different kind
+ of computer), type `make distclean'. There is also a `make
+ maintainer-clean' target, but that is intended mainly for the package's
+ developers. If you use it, you may have to get all sorts of other
+ programs in order to regenerate files that came with the distribution.
+
+ 6. You can also type `make uninstall' to remove the installed files again.
+
+ 7. This package provides `make distcheck', which can by used by developers to
+ test that all other targets like `make install' and `make uninstall' work
+ correctly. This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for details
+on some of the pertinent environment variables.
+
+You can give `configure' initial values for configuration parameters by setting
+variables in the command line or in the environment. Here is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the same
+time, by placing the object files for each architecture in their own directory.
+To do this, you can use GNU `make'. `cd' to the directory where you want the
+object files and executables to go and run the `configure' script. `configure'
+automatically checks for the source code in the directory that `configure' is
+in and in `..'. This is known as a "VPATH" build.
+
+With a non-GNU `make', it is safer to compile the package for one architecture
+at a time in the source code directory. After you have installed the package
+for one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+On MacOS X 10.5 and later systems, you can create libraries and executables
+that work on multiple system types--known as "fat" or "universal" binaries--by
+specifying multiple `-arch' options to the compiler but only a single `-arch'
+option to the preprocessor. Like this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+This is not guaranteed to produce working output in all cases, you may have to
+build one architecture at a time and combine the results using the `lipo' tool
+if you have problems.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You can
+specify an installation prefix other than `/usr/local' by giving `configure'
+the option `--prefix=PREFIX', where PREFIX must be an absolute file name.
+
+You can specify separate installation prefixes for architecture-specific files
+and architecture-independent files. If you pass the option
+`--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix
+for installing programs and libraries. Documentation and other data files
+still use the regular prefix.
+
+In addition, if you use an unusual directory layout you can give options like
+`--bindir=DIR' to specify different values for particular kinds of files. Run
+`configure --help' for a list of the directories you can set and what kinds of
+files go in them. In general, the default for these options is expressed in
+terms of `${prefix}', so that specifying just `--prefix' will affect all of the
+other directory specifications that were not explicitly provided.
+
+The most portable way to affect installation locations is to pass the correct
+locations to `configure'; however, many packages provide one or both of the
+following shortcuts of passing variable assignments to the `make install'
+command line to change installation locations without having to reconfigure or
+recompile.
+
+The first method involves providing an override variable for each affected
+directory. For example, `make install prefix=/alternate/directory' will choose
+an alternate location for all directory configuration variables that were
+expressed in terms of `${prefix}'. Any directories that were specified during
+`configure', but not in terms of `${prefix}', must each be overridden at
+install time for the entire installation to be relocated. The approach of
+makefile variable overrides for each directory variable is required by the GNU
+Coding Standards, and ideally causes no recompilation. However, some platforms
+have known limitations with the semantics of shared libraries that end up
+requiring recompilation when using this method, particularly noticeable in
+packages that use GNU Libtool.
+
+The second method involves providing the `DESTDIR' variable. For example,
+`make install DESTDIR=/alternate/directory' will prepend `/alternate/directory'
+before all installation names. The approach of `DESTDIR' overrides is not
+required by the GNU Coding Standards, and does not work on platforms that have
+drive letters. On the other hand, it does better at avoiding recompilation
+issues, and works well even when some directory options were not specified in
+terms of `${prefix}' at `configure' time.
+
+Optional Features
+=================
+
+This package pays attention to `--enable-FEATURE' options to `configure', where
+FEATURE indicates an optional part of the package. It also pays attention to
+`--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for
+the X Window System). The `README' should mention any `--enable-' and
+`--with-' options that the package recognizes.
+
+This package offers the ability to configure how verbose the execution of
+`make' will be. For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure --disable-silent-rules'
+sets the default to verbose, which can be overridden with `make V=0'.
+
+Particular systems
+==================
+
+On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not
+installed, it is recommended to use the following options in order to use an
+ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+HP-UX `make' updates targets which have the same time stamps as their
+prerequisites, which makes it generally unusable when shipped generated files
+such as `configure' are involved. Use GNU `make' instead.
+
+On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its
+`<wchar.h>' header file. The option `-nodtk' can be used as a workaround. If
+GNU CC is not installed, it is therefore recommended to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains
+several dysfunctional programs; working variants of these programs are
+available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it
+_after_ `/usr/bin'.
+
+On Haiku, software installed for all users goes in `/boot/common', not
+`/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically, but
+needs to determine by the type of machine the package will run on. Usually,
+assuming the package is built to be run on the _same_ architectures,
+`configure' can figure that out, but if it prints a message saying it cannot
+guess the machine type, give it the `--build=TYPE' option. TYPE can either be
+a short name for the system type, such as `sun4', or a canonical name which has
+the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+See the file `config.sub' for the possible values of each field.
+
+If you are _building_ compiler tools for cross-compiling, you should use the
+option `--target=TYPE' to select the type of system they will produce code for.
+
+If you want to _use_ a cross compiler, that generates code for a platform
+different from the build platform, you should specify the "host" platform
+(i.e., that on which the generated programs will eventually be run) with
+`--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you can
+create a site shell script called `config.site' that gives default values for
+variables like `CC', `cache_file', and `prefix'. `configure' looks for
+`PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it
+exists. Or, you can set the `CONFIG_SITE' environment variable to the location
+of the site script. A warning: not all `configure' scripts look for a site
+script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the environment
+passed to `configure'. However, some packages may run configure again during
+the build, and the customized values of these variables may be lost. In order
+to avoid this problem, you should set them in the `configure' command line,
+using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf limitation. Until the limitation is lifted, you can use
+this workaround:
+
+ CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..d46630e
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,50 @@
+# Makefile.am -- automake script for ppamltracer
+# Copyright (C) 2013 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = include src
+EXTRA_DIST = Doxyfile bindings examples
+dist-hook:
+ $(RM) `find $(distdir) -type f -name .gitignore`
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = ppamltracer.pc
+
+include $(srcdir)/Makefile_doxygen.am
+if DX_COND_doc
+MOSTLYCLEANFILES = $(DX_CLEANFILES)
+
+all-local: doc
+
+doc: doxygen-doc
+
+install-data-local: install-doxygen-doc
+install-doxygen-doc: $(DX_DOCDIR)/$(DX_PROJECT).tag
+ $(INSTALL) -d $(docdir)
+ cp -a $(DX_DOCDIR)/* $(docdir)
+
+uninstall-local: uninstall-doxygen-doc
+uninstall-doxygen-doc:
+ $(RM) -r $(docdir)/{html,latex,man,$(DX_PROJECT).{ps,pdf},rtf,xml}
+ $(RM) $(docdir)/$(DX_PROJECT).tag
+
+.PHONY: doc install-doxygen-doc uninstall-doxygen-doc
+endif DX_COND_doc
diff --git a/Makefile_doxygen.am b/Makefile_doxygen.am
new file mode 100644
index 0000000..73b1bf0
--- /dev/null
+++ b/Makefile_doxygen.am
@@ -0,0 +1,164 @@
+# Makefile_doxygen.am -- Makefile.am fragment to go along with AX_PROG_DOXYGEN
+# Copyright (C) 2009 Oren Ben-Kiki <oren@ben-kiki.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice and this
+# notice are preserved. This file is offered as-is, without any warranty.
+
+## --------------------------------- ##
+## Format-independent Doxygen rules. ##
+## --------------------------------- ##
+
+if DX_COND_doc
+
+## ------------------------------- ##
+## Rules specific for HTML output. ##
+## ------------------------------- ##
+
+if DX_COND_html
+
+DX_CLEAN_HTML = @DX_DOCDIR@/html
+
+endif DX_COND_html
+
+## ------------------------------ ##
+## Rules specific for CHM output. ##
+## ------------------------------ ##
+
+if DX_COND_chm
+
+DX_CLEAN_CHM = @DX_DOCDIR@/chm
+
+if DX_COND_chi
+
+DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
+
+endif DX_COND_chi
+
+endif DX_COND_chm
+
+## ------------------------------ ##
+## Rules specific for MAN output. ##
+## ------------------------------ ##
+
+if DX_COND_man
+
+DX_CLEAN_MAN = @DX_DOCDIR@/man
+
+endif DX_COND_man
+
+## ------------------------------ ##
+## Rules specific for RTF output. ##
+## ------------------------------ ##
+
+if DX_COND_rtf
+
+DX_CLEAN_RTF = @DX_DOCDIR@/rtf
+
+endif DX_COND_rtf
+
+## ------------------------------ ##
+## Rules specific for XML output. ##
+## ------------------------------ ##
+
+if DX_COND_xml
+
+DX_CLEAN_XML = @DX_DOCDIR@/xml
+
+endif DX_COND_xml
+
+## ----------------------------- ##
+## Rules specific for PS output. ##
+## ----------------------------- ##
+
+if DX_COND_ps
+
+DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
+
+DX_PS_GOAL = doxygen-ps
+
+doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
+
+@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
+ cd @DX_DOCDIR@/latex; \
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+ $(DX_LATEX) refman.tex; \
+ $(MAKEINDEX_PATH) refman.idx; \
+ $(DX_LATEX) refman.tex; \
+ countdown=5; \
+ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+ refman.log > /dev/null 2>&1 \
+ && test $$countdown -gt 0; do \
+ $(DX_LATEX) refman.tex; \
+ countdown=`expr $$countdown - 1`; \
+ done; \
+ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
+
+endif DX_COND_ps
+
+## ------------------------------ ##
+## Rules specific for PDF output. ##
+## ------------------------------ ##
+
+if DX_COND_pdf
+
+DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
+
+DX_PDF_GOAL = doxygen-pdf
+
+doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
+
+@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
+ cd @DX_DOCDIR@/latex; \
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+ $(DX_PDFLATEX) refman.tex; \
+ $(DX_MAKEINDEX) refman.idx; \
+ $(DX_PDFLATEX) refman.tex; \
+ countdown=5; \
+ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+ refman.log > /dev/null 2>&1 \
+ && test $$countdown -gt 0; do \
+ $(DX_PDFLATEX) refman.tex; \
+ countdown=`expr $$countdown - 1`; \
+ done; \
+ mv refman.pdf ../@PACKAGE@.pdf
+
+endif DX_COND_pdf
+
+## ------------------------------------------------- ##
+## Rules specific for LaTeX (shared for PS and PDF). ##
+## ------------------------------------------------- ##
+
+if DX_COND_latex
+
+DX_CLEAN_LATEX = @DX_DOCDIR@/latex
+
+endif DX_COND_latex
+
+.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
+
+doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
+ rm -rf @DX_DOCDIR@
+ $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
+
+DX_CLEANFILES = \
+ @DX_DOCDIR@/@PACKAGE@.tag \
+ -r \
+ $(DX_CLEAN_HTML) \
+ $(DX_CLEAN_CHM) \
+ $(DX_CLEAN_CHI) \
+ $(DX_CLEAN_MAN) \
+ $(DX_CLEAN_RTF) \
+ $(DX_CLEAN_XML) \
+ $(DX_CLEAN_PS) \
+ $(DX_CLEAN_PDF) \
+ $(DX_CLEAN_LATEX)
+
+endif DX_COND_doc
+
diff --git a/README b/README
new file mode 100644
index 0000000..9801594
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+ ppamltracer, v0.1.0
+
+ppamltracer is a lightweight tracing library designed for explicit instrmention
+of generated code. If you're writing a compiler and need hard data on your
+optimizer's efficacy, ppamltracer is the library for you.
+
+ppamltracer writes trace logs in the Open Trace Format [1], a free and open
+standard developed by the Zentrum für Informationsdienste und
+Hochleistungsrechnen (Center for Information Services and High-Performance
+Computing) at the Technical University of Dresden.
+
+This package contains the C code required to build the libppamltracer shared
+library, as well as bindings for Haskell, Racket, Python, and Java. While the
+bindings present idiomatic interfaces of various degrees of safety, they all
+rely on the shared library, so you'll need to install that first. For detailed
+installation instructions, see the INSTALL file.
+
+For examples that use the C API, see the examples directory. For examples that
+use the APIs presented by the various language bindings, see the READMEs
+associated with those bindings.
+
+
+[1] http://tu-dresden.de/die_tu_dresden/zentrale_einrichtungen/zih/forschung/projekte/otf
+[2] http://darpa.mil/Our_Work/I2O/Programs/Probabilistic_Programming_for_Advanced_Machine_Learning_(PPAML%29.aspx)
diff --git a/bindings/haskell/.gitignore b/bindings/haskell/.gitignore
new file mode 100644
index 0000000..805d057
--- /dev/null
+++ b/bindings/haskell/.gitignore
@@ -0,0 +1,7 @@
+# .gitignore for ppamltracer-haskell -*- conf -*-
+
+*.hi
+*.o
+dist*/
+
+examples/simple
diff --git a/bindings/haskell/README b/bindings/haskell/README
new file mode 100644
index 0000000..3d9cf39
--- /dev/null
+++ b/bindings/haskell/README
@@ -0,0 +1,8 @@
+ ppamltracer-haskell, v0.1.0
+
+This package contains Haskell bindings to ppamltracer. They require GHC 7.6 or
+later.
+
+This package uses the Cabal build system; normal Cabal build procedure applies.
+
+For examples of use, see the examples directory.
diff --git a/bindings/haskell/Setup.hs b/bindings/haskell/Setup.hs
new file mode 100644
index 0000000..fa38bd0
--- /dev/null
+++ b/bindings/haskell/Setup.hs
@@ -0,0 +1,22 @@
+{- Setup -- Cabal setup file for ppamltracer
+Copyright (C) 2014 Galois, Inc.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+
+To contact Galois, complete the Web form at <http://corp.galois.com/contact/> or
+write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, Oregon,
+97204-1622. -}
+
+import Distribution.Simple
+
+main = defaultMain
diff --git a/bindings/haskell/examples/simple.hs b/bindings/haskell/examples/simple.hs
new file mode 100644
index 0000000..478f25b
--- /dev/null
+++ b/bindings/haskell/examples/simple.hs
@@ -0,0 +1,46 @@
+{- simple.hs -- basic ppamltracer example
+This file is in the public domain.
+
+Compile this with
+ ghc --make simple.hs
+-}
+
+{-# LANGUAGE LambdaCase #-}
+module Main where
+
+import Control.Applicative ((<$>), (<*>))
+import Control.Monad (liftM)
+
+import PPAML.Tracer
+
+main :: IO ()
+main = do
+ -- Start ppamltracer.
+ withTracer "/tmp/simple_report" $ \tracer -> do
+ -- Register the factorial phase.
+ withPhase tracer "fact" $ \phase -> do
+ -- Print factorials.
+ putStr "Factorials:"
+ mapM_ (putStr . (' ':) . show) =<< mapM (fact phase) [0 .. 40]
+ putStrLn ""
+ -- Register the Fibonacci phase.
+ withPhase tracer "fib" $ \phase -> do
+ -- Print Fibonacci numbers.
+ putStr "Fibonacci numbers:"
+ mapM_ (putStr . (' ':) . show) =<< mapM (fib phase) [0 .. 25]
+ putStrLn ""
+
+{- Records that we're running inside the provided phase and computes a
+factorial. -}
+fact :: PhaseHandle -> Integer -> IO Integer
+fact phase = withPhaseRunning phase . \case
+ 0 -> return 1
+ n -> liftM (n*) $ fact phase (n - 1)
+
+{- Records that we're running inside the provided phase and computes a Fibonacci
+number. -}
+fib :: PhaseHandle -> Integer -> IO Integer
+fib phase = withPhaseRunning phase . \case
+ 0 -> return 0
+ 1 -> return 1
+ n -> (+) <$> fib phase (n - 1) <*> fib phase (n - 2)
diff --git a/bindings/haskell/ppamltracer.cabal b/bindings/haskell/ppamltracer.cabal
new file mode 100644
index 0000000..5b6918e
--- /dev/null
+++ b/bindings/haskell/ppamltracer.cabal
@@ -0,0 +1,62 @@
+-- ppamltracer.cabal -- Cabal build file for ppamltracer
+-- Copyright (C) 2014 Galois, Inc.
+--
+-- This program is free software: you can redistribute it and/or modify it under
+-- the terms of the GNU General Public License as published by the Free Software
+-- Foundation, either version 3 of the License, or (at your option) any later
+-- version.
+--
+-- This program is distributed in the hope that it will be useful, but WITHOUT
+-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+-- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+-- details.
+--
+-- You should have received a copy of the GNU General Public License along with
+-- this program. If not, see <http://www.gnu.org/licenses/>.
+--
+-- To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+-- or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+-- Oregon, 97204-1622.
+
+cabal-version: >=1.10
+name: ppamltracer
+version: 0.1.0
+synopsis: A lightweight tracing library
+description: ppamltracer is a lightweight tracing library designed for explicit
+ instrumention of generated code. If you’re writing a compiler and need hard
+ data on your optimizer’s efficacy, ppamltracer is the library for you. This
+ package uses Haskell’s foreign function interface to wrap the C libppamltracer
+ API.
+ .
+ ppamltracer writes trace logs in the
+ <http://tu-dresden.de/zih/otf/ Open Trace Format>, a free and open standard
+ developed by the Zentrum für Informationsdienste und Hochleistungsrechnen
+ (Center for Information Services and High-Performance Computing) at the
+ Technical University of Dresden.
+ .
+ We developed ppamltracer as part of DARPA’s
+ <http://darpa.mil/Our_Work/I2O/Programs/Probabilistic_Programming_for_Advanced_Machine_Learning_(PPAML%29.aspx Probabilistic Programming for Advancing Machine Learning>
+ (PPAML) project.
+copyright: © 2014 Galois, Inc.
+license: GPL-3
+author: Benjamin Barenblat
+maintainer: bbarenblat@galois.com
+category: Language
+build-type: Simple
+extra-source-files: examples/simple.hs
+tested-with: GHC==7.6.3
+
+library
+ hs-source-dirs: src
+ default-language: Haskell2010
+ other-extensions: DeriveDataTypeable
+ , EmptyDataDecls
+ , ExistentialQuantification
+ , TemplateHaskell
+ build-depends: base
+ , deepseq >=1.2.0.0 && <2
+ , hierarchical-exceptions <2
+ extra-libraries: ppamltracer
+ exposed-modules: PPAML.Tracer
+ other-modules: PPAML.Tracer.Exception
+ ghc-options: -Wall -O2
diff --git a/bindings/haskell/src/PPAML/Tracer.hs b/bindings/haskell/src/PPAML/Tracer.hs
new file mode 100644
index 0000000..ddff15c
--- /dev/null
+++ b/bindings/haskell/src/PPAML/Tracer.hs
@@ -0,0 +1,268 @@
+{- PPAML.Tracer -- PPAML timing instrumentation system (Haskell bindings)
+Copyright (C) 2014 Galois, Inc.
+
+This library is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This library is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this library. If not, see <http://www.gnu.org/licenses/>.
+
+To contact Galois, complete the Web form at <http://corp.galois.com/contact/> or
+write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, Oregon,
+97204-1622. -}
+
+{-| Getting started with ppamltracer is easy. Because of Haskell’s intrinsic
+laziness, though, getting meaningful results out of ppamltracer is slightly more
+difficult. For instance, consider the following (correctly written) example:
+
+> import PPAML.Tracer
+>
+> main =
+> withTracer "/tmp/my_report" $ \tracer ->
+> withPhase tracer "phase 1" $ \phase ->
+> withPhaseRunning phase doStuff
+> withPhase tracer "phase 2" $ \phase -> do
+> withPhaseRunning phase doOtherStuff
+> withPhaseRunning phase doYetMoreStuff
+
+This creates a report which appears to record the total runtime of 'doStuff'
+recorded as \"phase 1\" and the total runtime of 'doOtherStuff' and
+'doYetMoreStuff' combined as \"phase 2\". In actuality, however, the report
+does not record the total runtime – instead,
+
+> withPhaseRunning phase f
+
+records the time required to evaluate 'f'’s result to normal form. Thus, 'f'
+can leverage infinite data as intermediate values; only 'f'’s final result need
+be finite. -}
+
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE LambdaCase #-}
+module PPAML.Tracer
+ ( -- * Tracers
+ Tracer, TracerHandle
+ , withTracer
+ -- * Phases
+ , Phase, PhaseHandle
+ , withPhase
+ -- * Timing
+ , withPhaseRunning, withPhaseRunning_
+ -- * Exceptions
+ {-| ppamltracer defines a fairly detailed exception hierarchy; however,
+ all exceptions are truly exceptional cases, and they likely will not
+ occur in normal use. For reference, the hierarchy looks like this:
+
+ @
+'Control.Exception.SomeException'
+└─ 'TracerException'
+ ├─ 'OTFException'
+ │ ├─ 'OTFManagerException'
+ │ │ └─ 'OTFManagerInitializationFailure'
+ │ └─ 'OTFWriterException'
+ │ ├─ 'OTFWriterInitializationFailure'
+ │ ├─ 'OTFPhaseDefinitionFailure'
+ │ ├─ 'OTFPhaseEntryFailure'
+ │ ├─ 'OTFPhaseExitFailure'
+ │ ├─ 'OTFWriterCloseFailure'
+ │ ├─ 'OTFTraceResolutionFailure'
+ │ └─ 'OTFProcessDefinitionFailure'
+ └─ 'TimingException'
+ └─ 'ClockAcquisitionFailure'
+ @ -}
+ , TracerException
+ -- ** Open Trace Format exceptions
+ , OTFException
+ , OTFManagerException, OTFManagerInitializationFailure
+ , OTFWriterException, OTFWriterInitializationFailure,
+ OTFPhaseDefinitionFailure, OTFPhaseEntryFailure, OTFPhaseExitFailure,
+ OTFWriterCloseFailure, OTFTraceResolutionFailure,
+ OTFProcessDefinitionFailure
+ -- ** Timing exceptions
+ , TimingException, ClockAcquisitionFailure
+ ) where
+
+import Control.DeepSeq (NFData, ($!!))
+import Control.Exception (bracket_, throw)
+import Foreign (Storable, Ptr, allocaBytes, peek)
+import Foreign.C (CInt(CInt), CSize(CSize), CString, withCString)
+import System.IO.Unsafe (unsafeDupablePerformIO)
+
+import PPAML.Tracer.Exception
+
+
+-------------------------------- High-level API --------------------------------
+
+{-| Constructs a 'Tracer' and executes the specified computation. The trace
+report will be stored in Open Trace Format; all trace file paths will begin with
+the specified path.
+
+Throws:
+
+ * 'OTFManagerInitializationFailure' if the Open Trace Format manager could not
+ be initialized.
+
+ * 'OTFWriterInitializationFailure' if the Open Trace Format writer could not
+ be initialized.
+
+ * 'OTFTraceResolutionFailure' if setting the trace resolution failed.
+
+ * 'OTFProcessDefinitionFailure' if defining the main OTF process failed.
+
+ * 'OTFWriterCloseFailure' if the Open Trace Format writer could not be closed
+ after the computation ran. -}
+
+withTracer :: FilePath -> (TracerHandle -> IO a) -> IO a
+withTracer reportBaseName f =
+ allocaBytes tracerSize $ \tracerHandle ->
+ bracket_ (tracerInit tracerHandle reportBaseName)
+ (tracerDone tracerHandle)
+ (f tracerHandle)
+
+{-| Constructs a 'Phase' and executes the specified computation.
+
+Throws 'OTFPhaseDefinitionFailure' if the phase could not be defined. -}
+withPhase :: TracerHandle -- ^ the associated 'Tracer'
+ -> String -- ^ the name of the 'Phase'
+ -> (PhaseHandle -> IO a)
+ -> IO a
+withPhase tracer name f =
+ allocaBytes phaseSize $ \phaseHandle ->
+ bracket_ (phaseInit tracer phaseHandle name)
+ (phaseDone phaseHandle)
+ (f phaseHandle)
+
+{-| Executes an IO action and evaluates its result to normal form, recording the
+time required to do so in the provided 'Phase'. -}
+withPhaseRunning :: NFData a => PhaseHandle -> IO a -> IO a
+withPhaseRunning phase f = withPhaseRunning_ phase ((return $!!) =<< f)
+
+{-| Executes an IO action, recording the time required to do so in the provided
+'Phase'. Unlinke 'withPhaseRunning', this function does /not/ evaluate the
+action’s result. Use this function when you need finer-grained control over the
+precise degree of evaluation than 'withPhaseRunning' offers.
+-}
+withPhaseRunning_ :: PhaseHandle -> IO a -> IO a
+withPhaseRunning_ phase = bracket_ (phaseStart phase) (phaseStop phase)
+
+
+----------------------------------- Tracers ------------------------------------
+
+----- Data type -----
+
+{-| Tracer state bundle. ppamltracer is fundamentally a set of stateful
+operations; this data type dsecribes the state ppamltracer needs to operate
+properly. A one-to-one mapping exists between 'Tracer's and trace reports, so
+you will likely only need one 'Tracer' per program. -}
+data Tracer
+
+foreign import ccall unsafe "ppaml/tracer/internal.h & ppaml_tracer_t_size"
+ ppaml_tracer_t_size :: Ptr CSize
+
+tracerSize :: Int
+tracerSize = fromIntegral $ unsafeReadLibraryConstant ppaml_tracer_t_size
+
+
+----- Initialization and finalization -----
+
+type TracerHandle = Ptr Tracer
+
+foreign import ccall unsafe "ppaml/tracer.h ppaml_tracer_init"
+ ppaml_tracer_init :: TracerHandle -> CString -> IO CInt
+
+tracerInit :: TracerHandle -> FilePath -> IO ()
+tracerInit tracer reportNameBase =
+ withCString reportNameBase $ \cReportNameBase ->
+ ppaml_tracer_init tracer cReportNameBase >>= \case
+ 0 -> return ()
+ 1 -> throw OTFManagerInitializationFailure
+ 2 -> throw OTFWriterInitializationFailure
+ 3 -> throw OTFTraceResolutionFailure
+ 4 -> throw OTFProcessDefinitionFailure
+ r -> unexpectedReturnCode r
+
+foreign import ccall unsafe "ppaml/tracer.h ppaml_tracer_done"
+ ppaml_tracer_done :: TracerHandle -> IO CInt
+
+tracerDone :: TracerHandle -> IO ()
+tracerDone tracer =
+ ppaml_tracer_done tracer >>= \case 0 -> return ()
+ 1 -> throw OTFWriterCloseFailure
+ r -> unexpectedReturnCode r
+
+
+------------------------------------ Phases ------------------------------------
+
+----- Data type -----
+
+-- | A phase of execution to trace and to gather timing statistics about.
+data Phase
+
+foreign import ccall unsafe "ppaml/tracer/internal.h & ppaml_phase_t_size"
+ ppaml_phase_t_size :: Ptr CSize
+
+phaseSize :: Int
+phaseSize = fromIntegral $ unsafeReadLibraryConstant ppaml_phase_t_size
+
+
+----- Initialization and finalization -----
+
+type PhaseHandle = Ptr Phase
+
+foreign import ccall unsafe "ppaml/tracer.h ppaml_phase_init"
+ ppaml_phase_init :: TracerHandle -> PhaseHandle -> CString -> IO CInt
+
+phaseInit :: TracerHandle -> PhaseHandle -> String -> IO ()
+phaseInit tracer phase name =
+ withCString name $ \cName ->
+ ppaml_phase_init tracer phase cName >>= \case
+ 0 -> return ()
+ 1 -> throw OTFPhaseDefinitionFailure
+ r -> unexpectedReturnCode r
+
+foreign import ccall unsafe "ppaml/tracer.h ppaml_phase_done"
+ ppaml_phase_done :: PhaseHandle -> IO CInt
+
+phaseDone :: PhaseHandle -> IO ()
+phaseDone phase =
+ ppaml_phase_done phase >>= \case 0 -> return ()
+ r -> unexpectedReturnCode r
+
+
+----- Timing -----
+
+foreign import ccall unsafe "ppaml/tracer.h ppaml_phase_start"
+ ppaml_phase_start :: PhaseHandle -> IO CInt
+
+phaseStart :: PhaseHandle -> IO ()
+phaseStart phase =
+ ppaml_phase_start phase >>= \case 0 -> return ()
+ 1 -> throw ClockAcquisitionFailure
+ 2 -> throw OTFPhaseEntryFailure
+ r -> unexpectedReturnCode r
+
+foreign import ccall unsafe "ppaml/tracer.h ppaml_phase_stop"
+ ppaml_phase_stop :: PhaseHandle -> IO CInt
+
+phaseStop :: PhaseHandle -> IO ()
+phaseStop phase =
+ ppaml_phase_stop phase >>= \case 0 -> return ()
+ 1 -> throw ClockAcquisitionFailure
+ 2 -> throw OTFPhaseExitFailure
+ r -> unexpectedReturnCode r
+
+
+----------------------------------- Utility ------------------------------------
+
+unsafeReadLibraryConstant :: Storable a => Ptr a -> a
+unsafeReadLibraryConstant = unsafeDupablePerformIO . peek
+
+unexpectedReturnCode :: CInt -> a
+unexpectedReturnCode code =
+ error $ "unexpected return code " ++ show code ++ "\n\
+ \This is a bug in ppamltracer! Report it to the maintainers."
diff --git a/bindings/haskell/src/PPAML/Tracer/Exception.hs b/bindings/haskell/src/PPAML/Tracer/Exception.hs
new file mode 100644
index 0000000..ba77c84
--- /dev/null
+++ b/bindings/haskell/src/PPAML/Tracer/Exception.hs
@@ -0,0 +1,78 @@
+{- PPAML.Tracer.Exception -- exceptions used by ppamltracer
+Copyright (C) 2014 Galois, Inc.
+
+This library is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This library is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this library. If not, see <http://www.gnu.org/licenses/>.
+
+To contact Galois, complete the Web form at <http://corp.galois.com/contact/> or
+write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, Oregon,
+97204-1622. -}
+
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE TemplateHaskell #-}
+module PPAML.Tracer.Exception where
+
+import Control.Exception (SomeException(SomeException))
+import Control.Exception.Hierarchical (mkAbstractException, mkException)
+
+-- | A generic ppamltracer error. Extends 'SomeException'.
+mkAbstractException 'SomeException "TracerException"
+
+
+-------------------------------- OTF exceptions --------------------------------
+
+{-| An error related to Open Trace Format input and output. Extends
+'TracerException'. -}
+mkAbstractException 'TracerException "OTFException"
+
+-- | An error caused by the Open Trace Fromat manager. Extends 'OTFException'.
+mkAbstractException 'OTFException "OTFManagerException"
+
+{-| Failure to initialize the Open Trace Format manager. Extends
+'OTFManagerException'. -}
+mkException 'OTFManagerException "OTFManagerInitializationFailure"
+
+-- | An error caused by the Open Trace Format writer. Extends 'OTFException'.
+mkAbstractException 'OTFException "OTFWriterException"
+
+{-| Failure to initialize the Open Trace Format writer. Extends
+'OTFWriterException'. -}
+mkException 'OTFWriterException "OTFWriterInitializationFailure"
+
+-- | Failure to define a phase. Extends 'OTFWriterException'.
+mkException 'OTFWriterException "OTFPhaseDefinitionFailure"
+
+-- | Failure to record entry into a phase. Extends 'OTFWriterException'.
+mkException 'OTFWriterException "OTFPhaseEntryFailure"
+
+-- | Failure to record exit from a phase. Extends 'OTFWriterException'.
+mkException 'OTFWriterException "OTFPhaseExitFailure"
+
+{-| Failure to close the Open Trace Format writer. Extends
+'OTFWriterException'. -}
+mkException 'OTFWriterException "OTFWriterCloseFailure"
+
+-- | Failure to set the tracer resolution. Extends 'OTFWriterException'.
+mkException 'OTFWriterException "OTFTraceResolutionFailure"
+
+-- | Failure to define a process (i.e., a thread). Extends 'OTFWriterException'.
+mkException 'OTFWriterException "OTFProcessDefinitionFailure"
+
+
+------------------------------ Timing exceptions -------------------------------
+
+-- | An error related to system timers. Extends 'TracerException'.
+mkAbstractException 'TracerException "TimingException"
+
+-- | A failure to get the current clock time. Extends 'TimingException'.
+mkException 'TimingException "ClockAcquisitionFailure"
diff --git a/bindings/java/.gitignore b/bindings/java/.gitignore
new file mode 100644
index 0000000..32690c1
--- /dev/null
+++ b/bindings/java/.gitignore
@@ -0,0 +1,7 @@
+# .gitignore for ppamltracer-java -*- conf -*-
+
+build/
+dist/
+
+# Examples
+examples/dist
diff --git a/bindings/java/README b/bindings/java/README
new file mode 100644
index 0000000..b5d4bfb
--- /dev/null
+++ b/bindings/java/README
@@ -0,0 +1,12 @@
+ ppamltracer-java, v0.1.0
+
+This package contains Java bindings to ppamltracer. They require Java SE 5 or
+later.
+
+This package uses the Java Native Interface. Therefore, building it produces
+two artifacts: a jar, which you should install in your CLASSPATH, and a shared
+library, which you should install in your LD_LIBRARY_PATH. If you have both
+Ant and autotools installed, simply typing `ant' will build both artifacts and
+install them in the `dist' directory.
+
+For examples of use, see the examples directory.
diff --git a/bindings/java/build.xml b/bindings/java/build.xml
new file mode 100644
index 0000000..d4e57f6
--- /dev/null
+++ b/bindings/java/build.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- build.xml: Ant build file for ppamltracer
+Copyright (C) 2014 Galois, Inc.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+
+To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+Oregon, 97204-1622. -->
+
+<project name="ppamltracer-java" basedir="." default="link-and-package">
+
+ <property name="project.shortname" value="ppamltracer" />
+ <property name="project.version" value="0.1.0" />
+ <property name="package" value="com.galois.ppaml.tracer" />
+
+ <property name="src" location="src" />
+ <property name="src.java" location="${src}/java" />
+ <property name="src.c" location="${src}/c" />
+
+ <property name="build" location="build" />
+ <property name="build.classes" location="${build}/classes" />
+ <property name="build.native" location="${build}/native" />
+
+ <property name="dist" location="dist" />
+ <property name="doc" location="${dist}/doc" />
+
+ <target name="java.compile">
+ <mkdir dir="${build.classes}" />
+ <javac srcdir="${src}"
+ destdir="${build.classes}"
+ includeantruntime="false" />
+ </target>
+
+ <target name="java.package" depends="java.compile">
+ <mkdir dir="${dist}" />
+ <jar destfile="${dist}/${project.shortname}-${project.version}.jar"
+ basedir="${build.classes}" />
+ </target>
+
+ <!-- Assemble the native sources with their JNI-generated headers. -->
+ <target name="native.prepare" depends="java.compile">
+ <copy todir="${build.native}">
+ <fileset dir="${src.c}" />
+ </copy>
+ <javah classpath="${build.classes}"
+ class="${package}.Tracer,${package}.Phase"
+ destdir="${build.native}"
+ verbose="yes" />
+ </target>
+
+ <!-- Do the autotools dance. -->
+ <target name="native.autotools" depends="native.prepare">
+ <mkdir dir="${build.native}/m4" />
+ <exec executable="autoreconf"
+ dir="${build.native}"
+ failonerror="true">
+ <arg value="--install" />
+ <arg value="-Wall" />
+ </exec>
+ </target>
+
+ <target name="native.compile" depends="native.autotools">
+ <exec executable="./configure"
+ dir="${build.native}"
+ failonerror="true">
+ <arg value="--prefix=${dist}" />
+ </exec>
+ <exec executable="make" dir="${build.native}" failonerror="true" />
+ </target>
+
+ <target name="native.install" depends="native.compile">
+ <mkdir dir="${dist}" />
+ <exec executable="make" dir="${build.native}" failonerror="true">
+ <arg value="install" />
+ </exec>
+ </target>
+
+ <target name="compile" depends="java.compile,native.compile" />
+
+ <target name="link-and-package" depends="java.package,native.install" />
+
+ <target name="doc">
+ <javadoc sourcepath="${src}"
+ destdir="${doc}"
+ packagenames="${package}"
+ access="public">
+ <fileset dir="${src.java}">
+ <include name="**" />
+ </fileset>
+ </javadoc>
+ <!-- Work around CVE-2013-1571 (frame injection vulnerability in generated
+ docs.) Hopefully, you're running a new enough JDK that this isn't
+ necessary, but one can never assume. -->
+ <patch-javadoc dir="${doc}" />
+ </target>
+
+ <target name="clean">
+ <delete dir="${build}"/>
+ <delete dir="${dist}"/>
+ </target>
+
+ <!-- Task to work around CVE-2013-1571. See Ant #55132
+ <https://issues.apache.org/bugzilla/show_bug.cgi?id=55132>. -->
+ <macrodef name="patch-javadoc">
+ <attribute name="dir"/>
+ <attribute name="docencoding" default="${file.encoding}"/>
+ <sequential>
+ <replace encoding="@{docencoding}" summary="true" taskname="patch-javadoc">
+ <fileset dir="@{dir}" casesensitive="false" includes="**/index.html,**/index.htm,**/toc.html,**/toc.htm">
+ <not><contains text="function validURL(url) {" casesensitive="true" /></not>
+ </fileset>
+ <replacetoken><![CDATA[function loadFrames() {]]></replacetoken>
+ <replacevalue expandProperties="false"><![CDATA[if (targetPage != "" && !validURL(targetPage))
+ function validURL(url) { // FIXED FIXED FIXED
+ var pos = url.indexOf(".html");
+ if (pos == -1 || pos != url.length - 5)
+ return false;
+ var allowNumber = false;
+ var allowSep = false;
+ var seenDot = false;
+ for (var i = 0; i < url.length - 5; i++) {
+ var ch = url.charAt(i);
+ if ('a' <= ch && ch <= 'z' ||
+ 'A' <= ch && ch <= 'Z' ||
+ ch == '$' ||
+ ch == '_') {
+ allowNumber = true;
+ allowSep = true;
+ } else if ('0' <= ch && ch <= '9'
+ || ch == '-') {
+ if (!allowNumber)
+ return false;
+ } else if (ch == '/' || ch == '.') {
+ if (!allowSep)
+ return false;
+ allowNumber = false;
+ allowSep = false;
+ if (ch == '.')
+ seenDot = true;
+ if (ch == '/' && seenDot)
+ return false;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+ function loadFrames() {]]></replacevalue>
+ </replace>
+ </sequential>
+ </macrodef>
+
+</project>
diff --git a/bindings/java/examples/build.xml b/bindings/java/examples/build.xml
new file mode 100644
index 0000000..e7f6f4d
--- /dev/null
+++ b/bindings/java/examples/build.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- build.xml: Ant build file for ppamltracer Java examples
+Copyright (C) 2014 Galois, Inc.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+
+To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+Oregon, 97204-1622. -->
+
+<project name="ppamltracer-java-examples" basedir="." default="compile">
+
+ <property name="src" location="src" />
+
+ <property name="dist" location="dist" />
+ <property name="dist.classes" location="${dist}/classes" />
+
+
+ <target name="compile">
+ <mkdir dir="${dist.classes}" />
+ <javac srcdir="${src}"
+ destdir="${dist.classes}"
+ includeantruntime="true" />
+ </target>
+
+ <target name="clean">
+ <delete dir="${dist}"/>
+ </target>
+
+</project>
diff --git a/bindings/java/examples/src/com/galois/ppaml/tracer/examples/Simple.java b/bindings/java/examples/src/com/galois/ppaml/tracer/examples/Simple.java
new file mode 100644
index 0000000..a698573
--- /dev/null
+++ b/bindings/java/examples/src/com/galois/ppaml/tracer/examples/Simple.java
@@ -0,0 +1,84 @@
+/* Simple -- basic ppamltracer example
+ * This file is in the public domain. */
+
+package com.galois.ppaml.tracer.examples;
+
+import com.galois.ppaml.tracer.Phase;
+import com.galois.ppaml.tracer.Tracer;
+
+public class Simple {
+
+ protected Phase factPhase;
+
+ protected Phase fibPhase;
+
+ protected void go(Tracer tracer) {
+ // Register the phases.
+ factPhase = tracer.createPhase("fact");
+ fibPhase = tracer.createPhase("fib");
+
+ // Print factorials.
+ System.out.print("Factorials:");
+ for (int i = 0; i < 21; i++) {
+ System.out.print(" " + fact(i));
+ }
+ System.out.println();
+
+ // Print Fibonacci numbers.
+ System.out.print("Fibonacci numbers:");
+ for (int i = 0; i < 30; i++) {
+ System.out.print(" " + fib(i));
+ }
+ System.out.println();
+
+ // Finalize phases and exit.
+ factPhase.close();
+ fibPhase.close();
+ }
+
+ protected long fact(int n) {
+ // Record that we're running inside the factorial phase.
+ factPhase.start();
+ // Compute the factorial.
+ long result;
+ if (n == 0) {
+ result = 1;
+ } else {
+ result = n * fact(n - 1);
+ }
+ // Return the result.
+ factPhase.stop();
+ return result;
+ }
+
+ protected int fib(int n) {
+ // Record that we're running inside the Fibonacci phase.
+ fibPhase.start();
+ // Compute the nth Fibonacci number.
+ int result;
+ switch (n) {
+ case 0:
+ case 1:
+ result = n;
+ break;
+ default:
+ result = fib(n - 1) + fib(n - 2);
+ break;
+ }
+ // Return the result.
+ fibPhase.stop();
+ return result;
+ }
+
+ public static void main(String[] args) {
+ // Start ppamltracer.
+ Tracer tracer = new Tracer("/tmp/simple_report");
+
+ // Run the app.
+ (new Simple()).go(tracer);
+
+ // Finalize ppamltracer and exit.
+ tracer.close();
+ }
+
+}
diff --git a/bindings/java/src/c/Makefile.am b/bindings/java/src/c/Makefile.am
new file mode 100644
index 0000000..c30a4cf
--- /dev/null
+++ b/bindings/java/src/c/Makefile.am
@@ -0,0 +1,39 @@
+# Makefile.am -- automake script for ppamltracer-java (JNI wrapper)
+# Copyright (C) 2013, 2014 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+ACLOCAL_AMFLAGS = -I m4
+
+lib_LTLIBRARIES = libppamltracer_java.la
+libppamltracer_java_la_SOURCES = \
+ $(srcdir)/com_galois_ppaml_tracer_Phase.c \
+ $(srcdir)/com_galois_ppaml_tracer_Phase.h \
+ $(srcdir)/com_galois_ppaml_tracer_Tracer.c \
+ $(srcdir)/com_galois_ppaml_tracer_Tracer.h \
+ $(srcdir)/pointer.h
+libppamltracer_java_la_CFLAGS = \
+ -std=c99 \
+ -Wall \
+ -Wextra \
+ -Wno-unused-parameter \
+ -pedantic \
+ -I@JAVA_HOME@/include
+libppamltracer_java_la_LDFLAGS = \
+ $(AM_LDFLAGS) \
+ -export-symbols-regex '^Java_'
diff --git a/bindings/java/src/c/com_galois_ppaml_tracer_Phase.c b/bindings/java/src/c/com_galois_ppaml_tracer_Phase.c
new file mode 100644
index 0000000..76f346b
--- /dev/null
+++ b/bindings/java/src/c/com_galois_ppaml_tracer_Phase.c
@@ -0,0 +1,97 @@
+/* com_galois_ppaml_tracer_Phase.c -- JNI wrapper for com.galois.ppaml.tracer.Phase
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#include <stdlib.h>
+
+#include <ppaml/tracer.h>
+
+#include <jni.h>
+#include <com_galois_ppaml_tracer_Phase.h>
+
+#include "pointer.h"
+
+JNIEXPORT
+jlong JNICALL Java_com_galois_ppaml_tracer_Phase_mallocPhase(
+ JNIEnv *const env,
+ jclass Phase)
+{
+ return jlong_of_pointer(malloc(sizeof(ppaml_phase_t)));
+}
+
+JNIEXPORT
+jint JNICALL Java_com_galois_ppaml_tracer_Phase_ppaml_1phase_1init(
+ JNIEnv *const env,
+ jclass Phase,
+ jlong tracer,
+ jlong phase,
+ jstring name)
+{
+ jint r;
+ // Allocate memory.
+ const char *const cName = (*env)->GetStringUTFChars(env, name, NULL);
+ if (cName == NULL) {
+ r = -1;
+ goto done;
+ }
+ // Perform the operation.
+ r = ppaml_phase_init(
+ pointer_of_jlong(tracer),
+ pointer_of_jlong(phase),
+ cName);
+ // Clean up.
+done: (*env)->ReleaseStringUTFChars(env, name, cName);
+ return r;
+}
+
+JNIEXPORT
+jint JNICALL Java_com_galois_ppaml_tracer_Phase_ppaml_1phase_1done(
+ JNIEnv *const env,
+ jclass Phase,
+ jlong phase)
+{
+ return ppaml_phase_done(pointer_of_jlong(phase));
+}
+
+JNIEXPORT
+void JNICALL Java_com_galois_ppaml_tracer_Phase_freePhase(
+ JNIEnv *const env,
+ jclass Phase,
+ jlong phase)
+{
+ free(pointer_of_jlong(phase));
+}
+
+JNIEXPORT
+jint JNICALL Java_com_galois_ppaml_tracer_Phase_ppaml_1phase_1start(
+ JNIEnv *const env,
+ jclass Phase,
+ jlong phase)
+{
+ return ppaml_phase_start(pointer_of_jlong(phase));
+}
+
+JNIEXPORT
+jint JNICALL Java_com_galois_ppaml_tracer_Phase_ppaml_1phase_1stop(
+ JNIEnv *const env,
+ jclass Phase,
+ jlong phase)
+{
+ return ppaml_phase_stop(pointer_of_jlong(phase));
+}
diff --git a/bindings/java/src/c/com_galois_ppaml_tracer_Tracer.c b/bindings/java/src/c/com_galois_ppaml_tracer_Tracer.c
new file mode 100644
index 0000000..2c23966
--- /dev/null
+++ b/bindings/java/src/c/com_galois_ppaml_tracer_Tracer.c
@@ -0,0 +1,76 @@
+/* com_galois_ppaml_tracer_Tracer.c -- JNI wrapper for com.galois.ppaml.tracer.Tracer
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#include <stdlib.h>
+
+#include <ppaml/tracer.h>
+
+#include <jni.h>
+#include <com_galois_ppaml_tracer_Tracer.h>
+
+#include "pointer.h"
+
+JNIEXPORT
+jlong JNICALL Java_com_galois_ppaml_tracer_Tracer_mallocTracer(
+ JNIEnv *const env,
+ jclass Tracer)
+{
+ return jlong_of_pointer(malloc(sizeof(ppaml_tracer_t)));
+}
+
+JNIEXPORT
+jint JNICALL Java_com_galois_ppaml_tracer_Tracer_ppaml_1tracer_1init(
+ JNIEnv *const env,
+ jclass Tracer,
+ jlong tracer,
+ jstring reportNameBase)
+{
+ jint r;
+ // Allocate memory.
+ const char *const cReportNameBase =
+ (*env)->GetStringUTFChars(env, reportNameBase, NULL);
+ if (cReportNameBase == NULL) {
+ r = -1;
+ goto done;
+ }
+ // Perform the operation.
+ r = ppaml_tracer_init(pointer_of_jlong(tracer), cReportNameBase);
+ // Clean up.
+done: (*env)->ReleaseStringUTFChars(env, reportNameBase, cReportNameBase);
+ return r;
+}
+
+JNIEXPORT
+jint JNICALL Java_com_galois_ppaml_tracer_Tracer_ppaml_1tracer_1done(
+ JNIEnv *const env,
+ jclass Tracer,
+ jlong tracer)
+{
+ return ppaml_tracer_done(pointer_of_jlong(tracer));
+}
+
+JNIEXPORT
+void JNICALL Java_com_galois_ppaml_tracer_Tracer_freeTracer(
+ JNIEnv *const env,
+ jclass Tracer,
+ jlong tracer)
+{
+ free(pointer_of_jlong(tracer));
+}
diff --git a/bindings/java/src/c/configure.ac b/bindings/java/src/c/configure.ac
new file mode 100644
index 0000000..0d1556b
--- /dev/null
+++ b/bindings/java/src/c/configure.ac
@@ -0,0 +1,58 @@
+# configure.ac -- autoconf script for ppamltracer-java (JNI wrapper)
+# Copyright (C) 2013, 2014 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+# Fire up Autoconf.
+AC_PREREQ([2.69])
+AC_INIT([ppamltracer-java], [0.1.0], [bbarenblat@galois.com])
+
+# Fire up Automake.
+AM_INIT_AUTOMAKE([-Wall -Wno-gnu -Werror foreign no-dist-gzip dist-bzip2])
+AC_CONFIG_MACRO_DIR([m4])
+
+# Build quietly.
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+# Build a C library.
+AC_PROG_CC
+AC_PROG_CC_C99
+# Automake 1.12 seems to require this, but automake 1.11 doesn't recognize it.
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+LT_INIT
+
+# JNI
+AC_ARG_VAR([JAVA_HOME], [path to JDK installation])
+if test -z "$JAVA_HOME"; then
+ AC_MSG_ERROR([empty JAVA_HOME environment variable; please set it to the path to your JDK installation])
+fi
+AC_SUBST([JAVA_HOME])
+
+# ppamltracer
+AC_CHECK_HEADER([ppaml/tracer.h],
+ [],
+ [AC_MSG_ERROR([ppamltracer development headers are required (are they in C_INCLUDE_PATH?)])])
+AC_CHECK_LIB([ppamltracer], [ppaml_tracer_init],
+ [],
+ [AC_MSG_ERROR([libppamltracer is required (is it in LIBRARY_PATH?)])])
+
+# Generate Makefile.
+AC_CONFIG_FILES([Makefile])
+
+# All done.
+AC_OUTPUT
diff --git a/bindings/java/src/c/pointer.h b/bindings/java/src/c/pointer.h
new file mode 100644
index 0000000..123025d
--- /dev/null
+++ b/bindings/java/src/c/pointer.h
@@ -0,0 +1,38 @@
+/* pointer.h -- pointer <-> jlong casts
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#ifndef PPAML_TRACER_JAVA_POINTER_H
+#define PPAML_TRACER_JAVA_POINTER_H
+
+#include <stdint.h>
+
+#include <jni.h>
+
+inline void *pointer_of_jlong(const jlong value)
+{
+ return (void *)(intptr_t)value;
+}
+
+inline jlong jlong_of_pointer(void *const pointer)
+{
+ return (jlong)(intptr_t)pointer;
+}
+
+#endif
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/CWrapper.java b/bindings/java/src/java/com/galois/ppaml/tracer/CWrapper.java
new file mode 100644
index 0000000..5a7887a
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/CWrapper.java
@@ -0,0 +1,184 @@
+/* CWrapper -- wrapping C structures
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * A class which wraps a C structure and associated functions.
+ *
+ * <p> This class is intended to work hand-in-hand with Java Native Interface
+ * code that follows a four-stage lifecycle:
+ *
+ * <dl>
+ * <dt>Allocation</dt><dd>The system reserves memory and resources needed by
+ * the structure.</dd>
+ * <dt>Initialization</dt><dd>The system installs data into the structure to
+ * make it ready for use.</dd>
+ * <dt>Finalization</dt><dd>The system cleans up the data structure under the
+ * assumption that it will not be used anymore.</dd>
+ * <dt>Freeing</dt><dd>The system releases memory and resources needed by the
+ * structure.</dd>
+ * </dl>
+ *
+ * This class defines abstract methods associated with each of these phases; by
+ * defining contracts on them, it can then consolidate the phases into two
+ * concretely-implemented operations:
+ *
+ * <dl>
+ * <dt>Open</dt><dd>The system allocates and initializes the underlying
+ * structure.</dd>
+ * <dt>Close</dt><dd>The system finalizes and frees the underlying
+ * structure.</dd>
+ * </dl>
+ *
+ * <p> <b>This class is not intended to be instantiated directly. Only
+ * instantiate its concrete subclasses.
+ */
+abstract class CWrapper {
+
+ /**
+ * C pointer to the underlying data structure.
+ */
+ protected long cPointer;
+
+
+ /////////////////////////// Low-level life cycle ///////////////////////////
+
+ /**
+ * Reserves memory and resources needed by the structure.
+ *
+ * <p> <b>Precondition:</b> <code>cPointer</code> is <code>0</code>.
+ *
+ * <p> <b>Postcondition:</b> If allocation was successful,
+ * <code>cPointer</code> is not <code>0</code>.
+ */
+ abstract protected void allocateCPointer();
+
+ /**
+ * Installs data into the structure to make it ready for use.
+ *
+ * <p> <b>Precondition:</b> Allocation succeeded.
+ */
+ abstract protected void initializeCPointer();
+
+ /**
+ * Cleans up the structure under the assumption that it will not be used
+ * anymore.
+ *
+ * <p> <b>Precondition:</b> Initialization succeeded.
+ */
+ abstract protected void finalizeCPointer();
+
+ /**
+ * Releases memory and resources needed by the structure.
+ *
+ * <p> <b>Precondition:</b> <code>cPointer</code> is not <code>0</code>. <br>
+ * <b>Precondition:</b> Finalization succeeded.
+ *
+ * <p> <b>Postcondition:</b> <code>cPointer</code> is <code>0</code>.
+ */
+ abstract protected void freeCPointer();
+
+
+ ////////////////////////// High-level life cycle //////////////////////////
+
+ /**
+ * Allocates and initializes the underlying structure.
+ *
+ * @throws OpenedException the underlying structure has already been opened.
+ *
+ * @throws NativeOutOfMemoryError allocation failed.
+ */
+ protected synchronized void open() {
+ if (cPointer != 0) {
+ throw new OpenedException();
+ }
+ allocateCPointer();
+ if (cPointer == 0) {
+ throw new NativeOutOfMemoryError();
+ }
+ initializeCPointer();
+ }
+
+ /**
+ * Finalizes and frees the underlying structure.
+ *
+ * @throws ClosedException the underlying structure has already been closed.
+ */
+ public synchronized void close() {
+ if (cPointer == 0) {
+ throw new ClosedException();
+ }
+ finalizeCPointer();
+ freeCPointer();
+ cPointer = 0;
+ }
+
+
+ ////////////////////////// Associated exceptions //////////////////////////
+
+ /**
+ * Signals that the underlying structure is already open.
+ */
+ public class OpenedException extends java.lang.IllegalStateException {
+
+ static final long serialVersionUID = -7226578680647930527L;
+
+ /**
+ * Constructs a <code>CWrapper.OpenedException</code> with no detail
+ * message.
+ */
+ protected OpenedException() {
+ super();
+ }
+
+ }
+
+ /**
+ * Signals that the underlying structure is already closed.
+ */
+ public class ClosedException extends java.lang.IllegalStateException {
+
+ static final long serialVersionUID = -2471059099211958977L;
+
+ /**
+ * Constructs a <code>CWrapper.ClosedException</code> with no detail
+ * message.
+ */
+ protected ClosedException() {
+ super();
+ }
+
+ }
+
+
+ ////////////////////////////// Miscellaneous //////////////////////////////
+
+ @Override
+ protected void finalize() {
+ close();
+ }
+
+ @Override
+ protected Object clone() throws java.lang.CloneNotSupportedException {
+ throw new java.lang.CloneNotSupportedException();
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/ClockAcquisitionException.java b/bindings/java/src/java/com/galois/ppaml/tracer/ClockAcquisitionException.java
new file mode 100644
index 0000000..68b212d
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/ClockAcquisitionException.java
@@ -0,0 +1,35 @@
+/* ClockAcquisitionException -- failure to get the time
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to get the current time. This could be due to any number
+ * of operating-system dependent factors.
+ */
+public class ClockAcquisitionException extends TimingException {
+
+ static final long serialVersionUID = -5730008048750495655L;
+
+ protected ClockAcquisitionException() {
+ super("could not get current time");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/NativeOutOfMemoryError.java b/bindings/java/src/java/com/galois/ppaml/tracer/NativeOutOfMemoryError.java
new file mode 100644
index 0000000..7c5ca3e
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/NativeOutOfMemoryError.java
@@ -0,0 +1,38 @@
+/* NativeOutOfMemoryError -- failure to allocate with malloc
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to allocate on the native heap.
+ */
+public class NativeOutOfMemoryError extends java.lang.Error {
+
+ static final long serialVersionUID = 1826582972785125106L;
+
+ protected NativeOutOfMemoryError() {
+ super();
+ }
+
+ protected NativeOutOfMemoryError(String s) {
+ super(s);
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFException.java
new file mode 100644
index 0000000..a639c69
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFException.java
@@ -0,0 +1,34 @@
+/* OTFException -- signals an OTF-related failure
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure related to the Open Trace Format API.
+ */
+public class OTFException extends java.lang.RuntimeException {
+
+ static final long serialVersionUID = 29573934735841980L;
+
+ protected OTFException(String s) {
+ super(s);
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFManagerException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFManagerException.java
new file mode 100644
index 0000000..b41d528
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFManagerException.java
@@ -0,0 +1,34 @@
+/* OTFManagerException -- signals a failure related to the OTF manager
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure related to the Open Trace Format file manager.
+ */
+public class OTFManagerException extends OTFException {
+
+ static final long serialVersionUID = 9158227932426782179L;
+
+ protected OTFManagerException(String s) {
+ super(s);
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFManagerInitializationException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFManagerInitializationException.java
new file mode 100644
index 0000000..e4f61a0
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFManagerInitializationException.java
@@ -0,0 +1,34 @@
+/* OTFManagerInitializationException -- failure to start the OTF manager
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to initialize the Open Trace Format file manager.
+ */
+public class OTFManagerInitializationException extends OTFManagerException {
+
+ static final long serialVersionUID = 8357422459731580151L;
+
+ protected OTFManagerInitializationException() {
+ super("could not initialize Open Trace Format file manager");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterCloseException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterCloseException.java
new file mode 100644
index 0000000..6b08d7d
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterCloseException.java
@@ -0,0 +1,34 @@
+/* OTFWriterCloseException -- failure to close the OTF writer
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to close the Open Trace Format writer.
+ */
+public class OTFWriterCloseException extends OTFWriterException {
+
+ static final long serialVersionUID = -3744439236064694516L;
+
+ protected OTFWriterCloseException() {
+ super("could not close Open Trace Format writer");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterEntryException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterEntryException.java
new file mode 100644
index 0000000..e330941
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterEntryException.java
@@ -0,0 +1,34 @@
+/* OTFWriterEntryException -- failure to record phase entry
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to record {@link Phase} entry.
+ */
+public class OTFWriterEntryException extends OTFWriterException {
+
+ static final long serialVersionUID = -3863070199086068755L;
+
+ protected OTFWriterEntryException() {
+ super("could not record phase start");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterException.java
new file mode 100644
index 0000000..f1d0e3c
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterException.java
@@ -0,0 +1,34 @@
+/* OTFWriterException -- failure related to the OTF writer
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure related to the Open Trace Format writer.
+ */
+public class OTFWriterException extends OTFException {
+
+ static final long serialVersionUID = -8501407892120456005L;
+
+ protected OTFWriterException(String s) {
+ super(s);
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterExitException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterExitException.java
new file mode 100644
index 0000000..502e4bf
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterExitException.java
@@ -0,0 +1,34 @@
+/* OTFWriterExitException -- failure to record phase exit
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to record {@link Phase} entry.
+ */
+public class OTFWriterExitException extends OTFWriterException {
+
+ static final long serialVersionUID = 2672929667606300155L;
+
+ protected OTFWriterExitException() {
+ super("could not record phase end");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterInitializationException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterInitializationException.java
new file mode 100644
index 0000000..315ceb2
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterInitializationException.java
@@ -0,0 +1,34 @@
+/* OTFWriterInitializationException -- failure to start the OTF writer
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to initialize the Open Trace Format writer.
+ */
+public class OTFWriterInitializationException extends OTFWriterException {
+
+ static final long serialVersionUID = -160590670499907090L;
+
+ protected OTFWriterInitializationException() {
+ super("could not open Open Trace Format writer");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterPhaseDefinitionException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterPhaseDefinitionException.java
new file mode 100644
index 0000000..225b32b
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterPhaseDefinitionException.java
@@ -0,0 +1,34 @@
+/* OTFWriterPhaseDefinitionException -- failure to define an OTF phase
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to define a {@link Phase}.
+ */
+public class OTFWriterPhaseDefinitionException extends OTFWriterException {
+
+ static final long serialVersionUID = -5221693771344940262L;
+
+ protected OTFWriterPhaseDefinitionException() {
+ super("could not define phase");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterProcessDefinitionException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterProcessDefinitionException.java
new file mode 100644
index 0000000..dc95859
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterProcessDefinitionException.java
@@ -0,0 +1,34 @@
+/* OTFWriterProcessDefinitionException -- failure to define an OTF process
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to define an Open Trace Format process (thread).
+ */
+public class OTFWriterProcessDefinitionException extends OTFWriterException {
+
+ static final long serialVersionUID = -2403392867513685061L;
+
+ protected OTFWriterProcessDefinitionException(String processName) {
+ super("could not define Open Trace Format Process " + processName);
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterResolutionException.java b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterResolutionException.java
new file mode 100644
index 0000000..bccacc1
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/OTFWriterResolutionException.java
@@ -0,0 +1,34 @@
+/* OTFWriterResolutionException -- failure to set the trace resolution
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure to set the time resolution of a {@link Tracer}.
+ */
+public class OTFWriterResolutionException extends OTFWriterException {
+
+ static final long serialVersionUID = 7655059683403795873L;
+
+ protected OTFWriterResolutionException() {
+ super("could not set trace resolution");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/Phase.java b/bindings/java/src/java/com/galois/ppaml/tracer/Phase.java
new file mode 100644
index 0000000..23ed2f4
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/Phase.java
@@ -0,0 +1,220 @@
+/* Phase -- wrapped ppaml_phase_t
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * A phase of execution to trace. This class exports no public constructors;
+ * to instantiate it, use <code>Tracer.createPhase</code>.
+ */
+public final class Phase extends CWrapper {
+
+ /**
+ * The <code>Tracer</code> this phase is associated with.
+ */
+ private final Tracer tracer;
+
+ /**
+ * The name of the phase.
+ */
+ private final String name;
+
+ /**
+ * Creates and initializes a <code>Phase</code>. You should not call this;
+ * call {@link Tracer.createPhase} instead.
+ *
+ * @param tracer the {@link Tracer} to associate the <code>Phase</code>
+ * with.
+ *
+ * @param name the name of the phase.
+ */
+ protected Phase(Tracer tracer, final String name) {
+ this.tracer = tracer;
+ this.name = name;
+ super.open();
+ }
+
+
+ ////////////////////////// Low-level life cycle //////////////////////////
+
+ ///// JNI shared library /////
+
+ static {
+ System.loadLibrary("ppamltracer_java");
+ }
+
+ /**
+ * Wraps <code>malloc</code> to allocate a <code>ppaml_phase_t</code>.
+ *
+ * @return Same as <code>malloc</code>.
+ */
+ private static native long mallocPhase();
+
+ /**
+ * Wraps <code>ppaml_phase_init</code>.
+ *
+ * @return -1 if converting <code>name</code> from a <code>String</code> to
+ * a <code>char *</code> failed; all other return codes are the same as
+ * <code>ppaml_phase_init</code>.
+ */
+ private static native int ppaml_phase_init(
+ long tracer,
+ long phase,
+ final String reportNameBase);
+
+ /**
+ * Wraps <code>ppaml_phase_done</code>.
+ *
+ * @return Same as <code>ppaml_phase_done</code>.
+ */
+ private static native int ppaml_phase_done(long phase);
+
+ /**
+ * Wraps <code>free</code>.
+ */
+ private static native void freePhase(long phase);
+
+
+ ///// JNI adapter code /////
+
+ @Override
+ protected void allocateCPointer() {
+ this.cPointer = mallocPhase();
+ }
+
+ /**
+ * Installs data into the structure to make it ready for use.
+ *
+ * <p> <b>Precondition:</b> Initialization succeeded.
+ *
+ * @throws OutOfMemoryError converting <code>name</code> from a
+ * <code>String</code> to a <code>char *</code> failed.
+ *
+ * @throws OTFWriterPhaseDefinitionException defining the OTF phase failed.
+ */
+ @Override
+ protected void initializeCPointer() {
+ assert this.cPointer != 0;
+ assert tracer != null;
+ assert name != null;
+ final int r = ppaml_phase_init(tracer.cPointer, this.cPointer, name);
+ switch (r) {
+ case 0:
+ break;
+ case -1:
+ throw new java.lang.OutOfMemoryError(
+ "failed to convert Java string to C string");
+ case 1:
+ throw new OTFWriterPhaseDefinitionException();
+ default:
+ throw new UnexpectedReturnValueError(r);
+ }
+ }
+
+ @Override
+ protected void finalizeCPointer() {
+ assert this.cPointer != 0;
+ final int r = ppaml_phase_done(this.cPointer);
+ if (r != 0) {
+ throw new UnexpectedReturnValueError(r);
+ }
+ }
+
+ @Override
+ protected void freeCPointer() {
+ assert this.cPointer != 0;
+ freePhase(this.cPointer);
+ }
+
+
+ ////////////////////////// Starting and stopping //////////////////////////
+
+ ///// JNI shared library /////
+
+ /**
+ * Wraps <code>ppaml_phase_start</code>.
+ *
+ * @return Same as <code>ppaml_phase_start</code>.
+ */
+ private static native int ppaml_phase_start(long phase);
+
+ /**
+ * Wraps <code>ppaml_phase_stop</code>.
+ *
+ * @return Same as <code>ppaml_phase_stop</code>.
+ */
+ private static native int ppaml_phase_stop(long phase);
+
+
+ ///// JNI adapter code /////
+
+ /**
+ * Records the start of a <code>Phase</code>.
+ *
+ * @throws ClosedException the <code>Phase</code> has been closed.
+ *
+ * @throws ClockAcquisitionException getting the time failed.
+ *
+ * @throws OTFWriterEntryException recording the phase start failed.
+ */
+ public void start() {
+ if (this.cPointer == 0) {
+ throw new ClosedException();
+ }
+ final int r = ppaml_phase_start(this.cPointer);
+ switch (r) {
+ case 0:
+ break;
+ case 1:
+ throw new ClockAcquisitionException();
+ case 2:
+ throw new OTFWriterEntryException();
+ default:
+ throw new UnexpectedReturnValueError(r);
+ }
+ }
+
+ /**
+ * Records the end of a <code>Phase</code>.
+ *
+ * @throws ClosedException the <code>Phase</code> has been closed.
+ *
+ * @throws ClockAcquisitionException getting the time failed.
+ *
+ * @throws OTFWriterExitException recording the phase stop failed.
+ */
+ public void stop() {
+ if (this.cPointer == 0) {
+ throw new ClosedException();
+ }
+ final int r = ppaml_phase_stop(this.cPointer);
+ switch (r) {
+ case 0:
+ break;
+ case 1:
+ throw new ClockAcquisitionException();
+ case 2:
+ throw new OTFWriterExitException();
+ default:
+ throw new UnexpectedReturnValueError(r);
+ }
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/TimingException.java b/bindings/java/src/java/com/galois/ppaml/tracer/TimingException.java
new file mode 100644
index 0000000..da1afad
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/TimingException.java
@@ -0,0 +1,34 @@
+/* TimingException -- signals a timing failure
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals a failure related to timing.
+ */
+public class TimingException extends java.lang.RuntimeException {
+
+ static final long serialVersionUID = -1441057354704045107L;
+
+ protected TimingException(String s) {
+ super(s);
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/Tracer.java b/bindings/java/src/java/com/galois/ppaml/tracer/Tracer.java
new file mode 100644
index 0000000..fe0a180
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/Tracer.java
@@ -0,0 +1,163 @@
+/* Tracer -- wrapped ppaml_tracer_t
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * State class for ppamltracer.
+ *
+ * <p> ppamltracer is fundamentally a set of stateful operations; a
+ * <code>Tracer</code> object holds the state ppamltracer needs to operate
+ * properly.
+ */
+public final class Tracer extends CWrapper {
+
+ /**
+ * Base file path for trace report output.
+ */
+ private final String reportNameBase;
+
+ /**
+ * Creates and initializes a <code>Tracer</code>. The trace report will be
+ * stored in Open Trace Format.
+ *
+ * @param reportNameBase all trace file paths will begin with this path.
+ */
+ public Tracer(final String reportNameBase) {
+ this.reportNameBase = reportNameBase;
+ super.open();
+ }
+
+ /**
+ * Creates and initializes a {@link Phase} associated with this
+ * <code>Tracer</code>.
+ *
+ * @param name the name of the phase.
+ */
+ public Phase createPhase(final String name) {
+ return new Phase(this, name);
+ }
+
+
+ ////////////////////////// Low-level life cycle //////////////////////////
+
+ ///// JNI shared library /////
+
+ static {
+ System.loadLibrary("ppamltracer_java");
+ }
+
+ /**
+ * Wraps <code>malloc</code> to allocate a <code>ppaml_tracer_t</code>.
+ *
+ * @return Same as <code>malloc</code>.
+ */
+ private static native long mallocTracer();
+
+ /**
+ * Wraps <code>ppaml_tracer_init</code>.
+ *
+ * @return -1 if converting <code>reportNameBase</code> from a
+ * <code>String</code> to a <code>char *</code> failed; all other return
+ * codes are the same as <code>ppaml_tracer_init</code>.
+ */
+ private static native int ppaml_tracer_init(
+ long tracer,
+ final String reportNameBase);
+
+ /**
+ * Wraps <code>ppaml_tracer_done</code>.
+ *
+ * @return Same as <code>ppaml_tracer_done</code>.
+ */
+ private static native int ppaml_tracer_done(long tracer);
+
+ /**
+ * Wraps <code>free</code>.
+ */
+ private static native void freeTracer(long tracer);
+
+
+ ///// JNI adapter code /////
+
+ @Override
+ protected void allocateCPointer() {
+ this.cPointer = mallocTracer();
+ }
+
+ /**
+ * Installs data into the structure to make it ready for use.
+ *
+ * <p> <b>Precondition:</b> Initialization succeeded.
+ *
+ * @throws OutOfMemoryError converting <code>reportNameBase</code> from a
+ * <code>String</code> to a <code>char *</code> failed.
+ *
+ * @throws OTFManagerInitializationException the Open Trace Format file
+ * manager could not be initialized.
+ *
+ * @throws OTFWriterInitializationException the Open Trace Format writer
+ * could not be initialized.
+ *
+ * @throws OTFWriterResolutionException setting the trace resolution failed.
+ *
+ * @throws OTFWriterProcessDefinitionException defining the main OTF process
+ * failed.
+ */
+ @Override
+ protected void initializeCPointer() {
+ assert this.cPointer != 0;
+ assert reportNameBase != null;
+ final int r = ppaml_tracer_init(this.cPointer, reportNameBase);
+ switch (r) {
+ case 0:
+ break;
+ case -1:
+ throw new java.lang.OutOfMemoryError(
+ "failed to convert Java string to C string");
+ case 1:
+ throw new OTFManagerInitializationException();
+ case 2:
+ throw new OTFWriterInitializationException();
+ case 3:
+ throw new OTFWriterResolutionException();
+ case 4:
+ throw new OTFWriterProcessDefinitionException("main");
+ default:
+ throw new UnexpectedReturnValueError(r);
+ }
+ }
+
+ @Override
+ protected void finalizeCPointer() {
+ assert this.cPointer != 0;
+ final int r = ppaml_tracer_done(this.cPointer);
+ if (r != 0) {
+ throw new UnexpectedReturnValueError(r);
+ }
+ }
+
+ @Override
+ protected void freeCPointer() {
+ assert this.cPointer != 0;
+ freeTracer(this.cPointer);
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/UnexpectedReturnValueError.java b/bindings/java/src/java/com/galois/ppaml/tracer/UnexpectedReturnValueError.java
new file mode 100644
index 0000000..e536073
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/UnexpectedReturnValueError.java
@@ -0,0 +1,37 @@
+/* UnexpectedReturnValueError -- unexpected return value from C API
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+package com.galois.ppaml.tracer;
+
+/**
+ * Signals an unexpected return value from libppamltracer. If this error is
+ * thrown, it indicates a bug in ppamltracer, and you should report it to the
+ * developers.
+ */
+public class UnexpectedReturnValueError extends java.lang.Error {
+
+ static final long serialVersionUID = -2476858873119724922L;
+
+ protected UnexpectedReturnValueError(int r) {
+ super("unexpected return value " + r + "\n"
+ + "This is a bug in ppamltracer! Report it to the maintainers.");
+ }
+
+}
diff --git a/bindings/java/src/java/com/galois/ppaml/tracer/package-info.java b/bindings/java/src/java/com/galois/ppaml/tracer/package-info.java
new file mode 100644
index 0000000..f922274
--- /dev/null
+++ b/bindings/java/src/java/com/galois/ppaml/tracer/package-info.java
@@ -0,0 +1,80 @@
+/* package-info.java -- package information
+ * Copyright (C) 2014 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+/**
+ * A lightweight, portable tracing library for instrumenting generated code.
+ *
+ * <p> ppamltracer is a lightweight, portable tracing library designed for
+ * explicit instrumention of generated code. If you're writing a compiler and
+ * need hard data on your optimizer's efficacy, ppamltracer is the library for
+ * you. This Java package provides bindings to the libppamltracer C API.
+ *
+ * <p> This package's usage can be summed up in a few lines:
+ *
+ * <pre>
+ * // Create report.
+ * Tracer tracer = new Tracer("/tmp/my_report");
+ *
+ * // Register phase 1 and do stuff.
+ * Phase phase = tracer.createPhase("phase 1");
+ * phase.start();
+ * doStuff();
+ * phase.stop();
+ * phase.close();
+ *
+ * // Register phase 2 and do different stuff.
+ * phase = tracer.createPhase("phase 2");
+ * // Other stuff
+ * phase.start();
+ * doOtherStuff();
+ * phase.stop();
+ * // Yet more stuff
+ * phase.start();
+ * doYetMoreStuff();
+ * phase.stop();
+ *
+ * // Clean up.
+ * phase.close();
+ * tracer.close();
+ * </pre>
+ *
+ * <p> This creates a report with the total runtime of <code>doStuff</code>
+ * recorded as "phase 1" and the total runtime of <code>doOtherStuff</code> and
+ * <code>doYetMoreStuff</code> combined as "phase 2".
+ *
+ * <p> <code>com.galois.ppaml.tracer.examples.Simple</code>, included in the
+ * distribution, contains a more lengthy example.
+ *
+ * <p> ppamltracer writes trace logs in the
+ * <a href="http://tu-dresden.de/zih/otf/">Open Trace Format</a>, a free and
+ * open standard developed by the Zentrum für Informationsdienste und
+ * Hochleistungsrechnen (Center for Information Services and High-Performance
+ * Computing) at the Technical University of Dresden.
+ *
+ * <p> We developed ppamltracer as part of DARPA's
+ * <a href="http://darpa.mil/Our_Work/I2O/Programs/Probabilistic_Programming_for_Advanced_Machine_Learning_(PPAML).aspx">Probabilistic
+ * Programming for Advancing Machine Learning</a> (PPAML) project.
+ *
+ * @author Galois, Inc.
+ *
+ * @version 0.1.0
+ */
+
+package com.galois.ppaml.tracer;
diff --git a/bindings/python/.gitignore b/bindings/python/.gitignore
new file mode 100644
index 0000000..4ac65cb
--- /dev/null
+++ b/bindings/python/.gitignore
@@ -0,0 +1,8 @@
+# .gitignore for ppamltracer-python -*- conf -*-
+
+# Python
+*.pyc
+
+# distutils
+MANIFEST
+dist/
diff --git a/bindings/python/MANIFEST.in b/bindings/python/MANIFEST.in
new file mode 100644
index 0000000..6ec6c9b
--- /dev/null
+++ b/bindings/python/MANIFEST.in
@@ -0,0 +1,21 @@
+# MANIFEST.in -- manifest template for source distributions
+# Copyright (C) 2013 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+recursive-include examples *.py
diff --git a/bindings/python/README b/bindings/python/README
new file mode 100644
index 0000000..35a6bbd
--- /dev/null
+++ b/bindings/python/README
@@ -0,0 +1,11 @@
+ ppamltracer-python, v0.1.0
+
+This package provides Python bindings to ppamltracer. They require Python 2.7.
+
+This package uses distutils for installation; you can run
+
+ python setup.py install
+
+to install the package.
+
+For examples of use, see the examples directory.
diff --git a/bindings/python/examples/simple.py b/bindings/python/examples/simple.py
new file mode 100755
index 0000000..350c85a
--- /dev/null
+++ b/bindings/python/examples/simple.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# simple.py -- basic ppamltracer-python example
+# This file is in the public domain.
+
+import os
+import sys
+
+from ppamltracer import Tracer
+
+def main():
+ # Disable buffering on stdout so we can see the numbers as they are printed.
+ sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+ # Start ppamltracer.
+ with Tracer("/tmp/simple_report") as tracer:
+ # Register the factorial phase.
+ with tracer.create_phase("fact") as phase:
+ # Print factorials.
+ print "Factorials:",
+ for i in range(21):
+ print fact(phase, i),
+ print
+ # Register the Fibonacci phase.
+ with tracer.create_phase("fib") as phase:
+ # Print Fibonacci numbers.
+ print "Fibonacci numbers: ",
+ for i in range(24):
+ print fib(phase, i),
+ print
+
+def fact(phase, n):
+ # Record that we're running inside the factorial phase.
+ with phase.running():
+ # Compute the factorial.
+ if n == 0:
+ return 1
+ else:
+ return n * fact(phase, n - 1)
+
+def fib(phase, n):
+ # Record that we're running inside the Fibonacci phase.
+ with phase.running():
+ # Compute the nth Fibonacci number.
+ if n == 0 or n == 1:
+ return n
+ else:
+ return fib(phase, n - 1) + fib(phase, n - 2)
+
+if __name__ == '__main__':
+ main()
diff --git a/bindings/python/ppamltracer.py b/bindings/python/ppamltracer.py
new file mode 100644
index 0000000..dde85a3
--- /dev/null
+++ b/bindings/python/ppamltracer.py
@@ -0,0 +1,365 @@
+# ppamltracer -- Python bindings to ppamltracer
+# Copyright (C) 2013 Galois, Inc.
+#
+# This library is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This library is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this library. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+"""A tracing library for explicit instrumentation of generated code.
+
+ppamltracer is a lightweight, portable tracing library designed for
+explicit instrumention of generated code. If you're writing a compiler
+and need hard data on your optimizer's efficacy, ppamltracer is the
+library for you. ppamltracer-python provides a high-level Python API on
+top of the libppamltracer C API.
+
+ppamltracer-python's usage can be summed up in a couple lines:
+
+ from ppamltracer import Tracer
+ with Tracer("/tmp/my_report") as tracer:
+ with tracer.create_phase("phase 1") as phase:
+ with phase.running():
+ do_stuff()
+ with tracer.create_phase("phase 2") as phase:
+ with phase.running():
+ do_other_stuff()
+ with phase.running():
+ do_yet_more_stuff()
+
+This creates a report with the total runtime of do_stuff recorded as
+"phase 1", and the total runtime of do_other_stuff and do_yet_more_stuff
+combined as "phase 2".
+
+The ppamltracer-python distribution also contains a more lengthy example
+in the "examples" directory.
+
+ppamltracer writes trace logs in the Open Trace Format [1], a free and
+open standard developed by the Zentrum fuer Informationsdienste und
+Hochleistungsrechnen (Center for Information Services and
+High-Performance Computing) at the Technical University of Dresden.
+
+We developed ppamltracer and ppamltracer-python as part of DARPA's
+Probabilistic Programming for Advancing Machine Learning (PPAML)
+project [2].
+
+References:
+ [1] http://tu-dresden.de/zih/otf/
+ [2] http://darpa.mil/Our_Work/I2O/Programs/Probabilistic_Programming_for_Advanced_Machine_Learning_(PPAML).aspx
+"""
+# TODO: Replace "ue" in "fuer" with Unicode u-with-diaresis (blocking on
+# deployment of fix to Python #1065986, "Fix pydoc crashing on unicode
+# strings").
+
+import ctypes
+import ctypes.util
+import warnings
+
+
+################################ Low-level API ################################
+
+_lib = ctypes.cdll.LoadLibrary(ctypes.util.find_library("ppamltracer"))
+"""ctypes binding to the ppamltracer C library."""
+
+# The code in this section binds the C API using ctypes, translating
+# return codes into the exception hierarchy defined below. Since these
+# functions are not intended to be used externally, they're not
+# documented using pydoc; see the ppamltracer C API documentation for
+# information on their behavior.
+
+_sizeof_ppaml_tracer_t = \
+ ctypes.c_size_t.in_dll(_lib, "ppaml_tracer_t_size").value
+
+_sizeof_ppaml_phase_t = ctypes.c_size_t.in_dll(_lib, "ppaml_phase_t_size").value
+
+def _ppaml_tracer_init(tracer, report_name_base):
+ result = _lib.ppaml_tracer_init(tracer, report_name_base)
+ if result == 0:
+ return None
+ elif result == 1:
+ raise OTFManagerInitializationError()
+ elif result == 2:
+ raise OTFWriterInitializationError()
+ elif result == 3:
+ raise OTFWriterResolutionError()
+ elif result == 4:
+ raise OTFWriterProcessDefinitionError("main")
+ else:
+ _warn_unexpected_return_code()
+ raise TracerError()
+
+def _ppaml_tracer_done(tracer):
+ result = _lib.ppaml_tracer_done(tracer)
+ if result == 0:
+ return None
+ elif result == 1:
+ raise OTFWriterCloseError()
+ else:
+ _warn_unexpected_return_code()
+ raise TracerError()
+
+def _ppaml_phase_init(tracer, phase, name):
+ result = _lib.ppaml_phase_init(tracer, phase, name)
+ if result == 0:
+ return None
+ elif result == 1:
+ raise OTFWriterPhaseDefinitionError()
+ else:
+ _warn_unexpected_return_code()
+ raise TracerError()
+
+def _ppaml_phase_start(phase):
+ result = _lib.ppaml_phase_start(phase)
+ if result == 0:
+ return None
+ elif result == 1:
+ raise ClockAcquisitionError()
+ elif result == 2:
+ raise OTFWriterEntryError()
+ else:
+ _warn_unexpected_return_code()
+ raise TracerError()
+
+def _ppaml_phase_stop(phase):
+ result = _lib.ppaml_phase_stop(phase)
+ if result == 0:
+ return None
+ elif result == 1:
+ raise ClockAcquisitionError()
+ elif result == 2:
+ raise OTFWriterExitError()
+ else:
+ _warn_unexpected_return_code()
+ raise TracerError()
+
+def _ppaml_phase_done(phase):
+ result = _lib.ppaml_phase_done(phase)
+ if result == 0:
+ return None
+ else:
+ _warn_unexpected_return_code()
+ raise TracerError()
+
+
+############################# Resource-based API ##############################
+
+class Tracer(object):
+ """A tracer for programs, which records execution timing information.
+
+ This class is designed to be used with Python's "with" statement-- e.g.,
+
+ with Tracer("/tmp/my_report") as tracer:
+ main(tracer)
+
+ """
+
+ def __init__(self, report_name_base):
+ """Create a new tracer.
+
+ The tracer will create an Open Trace Format report during program
+ execution. The multiple files of the report will all start with the
+ specified base name.
+
+ """
+ self._report_name_base = report_name_base
+ self._underlying = None
+
+ def __enter__(self):
+ if self._underlying is None:
+ self._underlying = \
+ ctypes.create_string_buffer(_sizeof_ppaml_tracer_t)
+ _ppaml_tracer_init(self._underlying, self._report_name_base)
+ return self
+
+ def __exit__(self, *exception_info):
+ if self._underlying is not None:
+ _ppaml_tracer_done(self._underlying)
+ self._underlying = None
+
+ def create_phase(self, name):
+ """Construct a Phase associated with this Tracer.
+
+ This function is merely a convenience function; internally, it shells
+ out to the Phase constructor.
+
+ """
+ return Phase(self, name)
+
+
+class Phase(object):
+ """A phase of computation traced by ppamltracer.
+
+ This class is designed to be used with Python's "with" statement-- e.g.,
+
+ with Phase(tracer, "my phase") as phase:
+ with phase.running():
+ do_stuff()
+ with phase.running():
+ do_stuff_again()
+
+ Note the double use of "with". The outer "with" manages the lifetime of
+ a Phase; the inner "with" actually starts and stops the phase timer.
+
+ """
+
+ def __init__(self, tracer, name):
+ """Define a new phase tracked by a given tracer."""
+ self._tracer = tracer
+ self._name = name
+ self._underlying = None
+
+ def __enter__(self):
+ if self._underlying is None:
+ self._underlying = \
+ ctypes.create_string_buffer(_sizeof_ppaml_phase_t)
+ _ppaml_phase_init(
+ self._tracer._underlying,
+ self._underlying,
+ self._name)
+ return self
+
+ def __exit__(self, *exception_info):
+ if self._underlying is not None:
+ _ppaml_phase_done(self._underlying)
+ self._underlying = None
+
+ def _start(self):
+ _ppaml_phase_start(self._underlying)
+
+ def _stop(self):
+ _ppaml_phase_stop(self._underlying)
+
+ def running(self):
+ """ Create a resource manager for the phase timer.
+
+ This manager handles starting and stopping the phase, allowing you to
+ time operations by saying, e.g.,
+
+ with phase.running():
+ do_stuff()
+
+ """
+ return _PhaseTimerManager(self)
+
+
+class _PhaseTimerManager(object):
+ """Manage entry and exit from a Phase using the "with" statement."""
+
+ def __init__(self, phase):
+ self._phase = phase
+
+ def __enter__(self):
+ self._phase._start()
+
+ def __exit__(self, *exception_info):
+ self._phase._stop()
+
+
+############################# Exception hierarchy #############################
+
+class TracerError(Exception):
+ """A generic ppamltracer error."""
+ pass
+
+class OTFError(TracerError):
+ """An error related to Open Trace Format input and output."""
+ pass
+
+class OTFManagerError(OTFError):
+ """An error caused by the Open Trace Format manager."""
+ pass
+
+class OTFManagerInitializationError(OTFManagerError):
+ """Failure to initialize the Open Trace Format manager."""
+
+ def __init__(self):
+ super.__init__(
+ self,
+ "could not initialize Open Trace Format file manager")
+
+class OTFWriterError(OTFError):
+ """An error caused by the Open Trace Format writer."""
+ pass
+
+class OTFWriterInitializationError(OTFWriterError):
+ """Failure to initialize the Open Trace Format writer."""
+
+ def __init__(self):
+ super.__init__(self, "could not open Open Trace Format writer")
+
+class OTFWriterPhaseDefinitionError(OTFWriterError):
+ """Failure to define a phase. """
+
+ def __init__(self):
+ super.__init__(self, "could not define phase")
+
+class OTFWriterEntryError(OTFWriterError):
+ """Failure to record entry into a phase."""
+
+ def __init__(self):
+ super.__init__(self, "could not record phase start")
+
+class OTFWriterExitError(OTFWriterError):
+ """Failure to record exit from a phase."""
+
+ def __init__(self):
+ super.__init__(self, "could not record phase end")
+
+class OTFWriterCloseError(OTFWriterError):
+ """Failure to close the Open Trace Format writer."""
+
+ def __init__(self):
+ super.__init__(self, "could not close Open Trace Format writer")
+
+class OTFWriterResolutionError(OTFWriterError):
+ """Failure to set the tracer resolution."""
+
+ def __init__(self):
+ super.__init__(self, "could not set trace resolution")
+
+class OTFWriterProcessDefinitionError(OTFWriterError):
+ """Failure to define an Open Trace Format process."""
+
+ def __init__(self, process_name=None):
+ if process_name is None:
+ super.__init__(self, "could not define Open Trace Format process")
+ else:
+ super.__init__(self,
+ ("could not define Open Trace Format process \""
+ + process_name
+ + "\""))
+
+class TimingError(TracerError):
+ """An error related to system timers."""
+ pass
+
+class ClockAcquisitionError(TimingError):
+ """A failure to get the current clock time."""
+
+ def __init__(self):
+ super.__init__(self, "could not get current time")
+
+
+############################### Warnings ###############################
+
+class UnwrappedCErrorWarning(Warning):
+ """A warning indicating a failure to correctly wrap a C API."""
+ pass
+
+def _warn_unexpected_return_code():
+ warnings.warn(("Unexpected C return code\n"
+ + "*** This is a bug in ppamltracer-python! Report it to the maintainers."),
+ UnwrappedCErrorWarning,
+ 2)
diff --git a/bindings/python/setup.py b/bindings/python/setup.py
new file mode 100755
index 0000000..d8e9ec2
--- /dev/null
+++ b/bindings/python/setup.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# setup.py -- distutils setup script for ppamltracer-python
+# Copyright (C) 2013 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+from distutils.core import setup
+
+setup(name="ppamltracer-python",
+ version="0.1.0",
+ description="ppamltracer Python bindings",
+ author="Benjamin Barenblat",
+ author_email="bbarenblat@galois.com",
+ classifiers=["Development Status :: 4 - Beta",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: GNU General Public License (GPL)",
+ "Topic :: Software Development :: Compilers"],
+ license="GPL",
+ py_modules=['ppamltracer'])
diff --git a/bindings/racket/.gitignore b/bindings/racket/.gitignore
new file mode 100644
index 0000000..9f3ac02
--- /dev/null
+++ b/bindings/racket/.gitignore
@@ -0,0 +1,16 @@
+# .gitignore for ppamltracer-racket -*- conf -*-
+
+# Bytecode
+compiled/
+*.dep
+*.zo
+
+# Scribble
+manual/
+*.html
+*.tex
+*.pdf
+racket.css
+scribble.css
+scribble-style.css
+scribble-common.js
diff --git a/bindings/racket/README b/bindings/racket/README
new file mode 100644
index 0000000..b6c9d06
--- /dev/null
+++ b/bindings/racket/README
@@ -0,0 +1,11 @@
+ ppamltracer-racket, v0.1.0
+
+This package contains Racket bindings to ppamltracer. It requires Racket v5.2
+or later.
+
+Currently, this package is designed to be used as a collection; to install it,
+you should type `raco link --name ppamltracer .'. (You may uninstall it with
+`raco link --remove ppamltracer'.)
+
+To build the documentation, which contains a detailed example of use, you
+should run `scribble ++xref-in setup/xref load-collections-xref manual.scrbl'.
diff --git a/bindings/racket/main.rkt b/bindings/racket/main.rkt
new file mode 100644
index 0000000..e4db143
--- /dev/null
+++ b/bindings/racket/main.rkt
@@ -0,0 +1,396 @@
+#lang racket/base
+#| ppamltracer -- Racket bindings to ppamltracer
+Copyright (C) 2013, 2014 Galois, Inc.
+
+This library is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This library is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this library. If not, see <http://www.gnu.org/licenses/>.
+
+To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+Oregon, 97204-1622. |#
+
+(require (for-syntax racket/base
+ racket/syntax
+ (only-in racket/list drop-right)
+ (only-in racket/string string-join)
+ (only-in srfi/13 string-tokenize)
+ (only-in srfi/14 char-set char-set-complement)
+ srfi/26; hole notation
+ ))
+
+(require (rename-in ffi/unsafe [-> ~>])
+ ffi/unsafe/define)
+(require racket/contract)
+
+#| A shorthand for 'let-syntax-rule' with only one macro. For example,
+
+ (let-syntax-rule (take-fst x y) x
+ (take-fst 'foo 'bar))
+
+expands to
+
+ 'foo
+|#
+(define-syntax-rule (let-syntax-rule (name . args) template body)
+ (let-syntax ([name (syntax-rules () [(_ . args) template])])
+ body))
+
+;; Convenience macro to instantiate an exception at the current location.
+(define-syntax-rule (fail exception args ...)
+ (apply exception (list args ... (current-continuation-marks))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Low-level interface ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Load the library.
+(define-ffi-definer define-ppamltracer (ffi-lib "libppamltracer"))
+
+#| We're going to model ppaml_tracer_t and ppaml_phase_t as abstract types by
+having Racket treat them as buffers. These two symbols define how long those
+buffers need to be. Ideally, they should be of type 'size_t', but Racket
+doesn't have a size_t builtin, so we just use the largest C unsigned integer
+type. |#
+(define-ppamltracer ppaml_tracer_t_size _uint64)
+(define-ppamltracer ppaml_phase_t_size _uint64)
+
+#| Define the struct types we're working with as buffer types. Instead of
+mucking around with initializers and finalizers, which we can't seem to get
+working correctly, we simply export an API which enforces proper resource
+cleanup. |#
+(define (make-buffer size) (make-ctype (_bytes o size) #f #f))
+(define _ppaml_tracer_t (make-buffer ppaml_tracer_t_size))
+(define _ppaml_phase_t (make-buffer ppaml_phase_t_size))
+
+#| To help avoid passing structs of the wrong type in API internals, we'll
+manipulate the structs as tagged pointers. |#
+(define _tracer (_cpointer 'ppaml_tracer_t))
+(define _phase (_cpointer 'ppaml_phase_t))
+
+;; Allocation functions for _tracer and _phase.
+(define (malloc-tagged-pointer size-or-type tag)
+ (let ([result (malloc size-or-type 'atomic)])
+ (cpointer-push-tag! result tag)
+ result))
+(define (malloc-_tracer)
+ (malloc-tagged-pointer _ppaml_tracer_t 'ppaml_tracer_t))
+(define (malloc-_phase)
+ (malloc-tagged-pointer _ppaml_phase_t 'ppaml_phase_t))
+
+;; Import library functions.
+(define-ppamltracer ppaml_tracer_init (_fun _tracer _path ~> _int))
+(define-ppamltracer ppaml_tracer_done (_fun _tracer ~> _int))
+(define-ppamltracer ppaml_phase_init (_fun _tracer _phase _string ~> _int))
+(define-ppamltracer ppaml_phase_done (_fun _phase ~> _int))
+(define-ppamltracer ppaml_phase_start (_fun _phase ~> _int))
+(define-ppamltracer ppaml_phase_stop (_fun _phase ~> _int))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Error handling ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#| Convenience macro to create an exception. For example,
+
+ (define-exception exn:fail:whatever)
+
+expands to
+
+ (struct exn:fail:whatever exn:fail ()
+ #:extra-constructor-name make-exn:fail:whatever
+ #:transparent)
+
+You can also call 'define-exception' with a message. Then, instead of creating
+an extra binary make-prefixed constructor, 'define-exception' will create an
+extra /unary/ make-prefixed constructor. All instances of the exception will
+then have the same message. For example,
+
+ (define-exception exn:fail:whatever "whatever happened!")
+
+expands to
+
+ (struct exn:fail:whatever exn:fail ()
+ #:transparent)
+ (define (make-exn:fail:whatever continuation-mark-set)
+ (exn:fail:whatever "whatever happened!" continuation-mark-set))
+|#
+(define-syntax (define-exception stx)
+ (let ([#| Lifts a function which operates on data to operate on syntax
+ instead. |#
+ map-as-datum
+ (lambda (f stx) (datum->syntax stx (f (syntax->datum stx))))]
+ [#| Given an exception name (as a symbol), produces the conventional
+ super-exception. For instance,
+
+ (take-base-exn 'exn:fail:whatever)
+
+ expands to
+
+ 'exn:fail
+ |#
+ take-base-exn
+ (compose1 string->symbol
+ (cut string-join <> ":")
+ (cut drop-right <> 1)
+ (cut string-tokenize <> (char-set-complement
+ (char-set #\:)))
+ symbol->string)])
+ (syntax-case stx ()
+ [(_ name)
+ (with-syntax ([base-name (map-as-datum take-base-exn #'name)]
+ [make-name (format-id stx "make-~a" #'name
+ #:source #'name)])
+ #'(struct name base-name ()
+ #:extra-constructor-name make-name
+ #:transparent))]
+ [(_ name message)
+ (with-syntax ([base-name (map-as-datum take-base-exn #'name)]
+ [make-name (format-id stx "make-~a" #'name
+ #:source #'name)])
+ #'(begin
+ (struct name base-name () #:transparent)
+ (define (make-name continuation-mark-set)
+ (name message continuation-mark-set))))])))
+
+#| Like define-exception, but does not create an extra make-prefixed
+constructor at all. |#
+(define-syntax (define-exception* stx)
+ (let ([map-as-datum
+ (lambda (f stx) (datum->syntax stx (f (syntax->datum stx))))]
+ [take-base-exn
+ (compose1 string->symbol
+ (cut string-join <> ":")
+ (cut drop-right <> 1)
+ (cut string-tokenize <> (char-set-complement
+ (char-set #\:)))
+ symbol->string)])
+ (syntax-case stx ()
+ [(_ name)
+ (with-syntax ([base-name (map-as-datum take-base-exn #'name)])
+ #'(struct name base-name () #:transparent))])))
+
+;;;;; Exception hierarchy ;;;;;
+
+(define-exception exn:fail:ppamltracer)
+
+(define-exception exn:fail:ppamltracer:otf)
+
+(define-exception exn:fail:ppamltracer:otf:manager)
+
+(define-exception exn:fail:ppamltracer:otf:manager:initialization
+ "could not initialize Open Trace Format file manager")
+
+(define-exception exn:fail:ppamltracer:otf:writer)
+
+(define-exception exn:fail:ppamltracer:otf:writer:initialization
+ "could not open Open Trace Format writer")
+
+(define-exception exn:fail:ppamltracer:otf:writer:phase-definition
+ "could not define phase")
+
+(define-exception exn:fail:ppamltracer:otf:writer:entry
+ "could not record phase start")
+
+(define-exception exn:fail:ppamltracer:otf:writer:exit
+ "could not record phase end")
+
+(define-exception exn:fail:ppamltracer:otf:writer:close
+ "could not close Open Trace Format writer")
+
+(define-exception exn:fail:ppamltracer:otf:writer:resolution
+ "could not set trace resolution")
+
+(define-exception* exn:fail:ppamltracer:otf:writer:process-definition)
+(define (make-exn:fail:ppamltracer:otf:writer:process-definition
+ process-name
+ continuation-mark-set)
+ (exn:fail:ppamltracer:otf:writer:process-definition
+ (format "could not define Open Trace Format process ~v" process-name)
+ continuation-mark-set))
+
+(define-exception exn:fail:ppamltracer:timing)
+
+(define-exception exn:fail:ppamltracer:timing:clock-acquisition
+ "could not get current time")
+
+
+;;;;; Error-checked versions of library functions ;;;;;
+
+#| This macro makes checking C return codes trivial. Invocation is analogous
+to that for the 'cond' form:
+
+ (define some-function
+ (checked some-c-function
+ [0 'ok]
+ [1 (exn make-exn:fail:ppamltracer "bad data format")]
+ [-1 'ok]))
+
+This defines 'some-function' as a function taking an arbitrary number of
+arguments. 'some-function', when invoked, will pass all its arguments to
+'some-c-function'. If 'some-c-function' returns 0 or -1, then some-function
+will evaluate successfully to whatever 'some-c-function' returned; if
+'some-c-function' returns 1, though, 'some-function' will raise an
+'exn:fail:ppamltracer' exception with the specified error message.
+
+If 'some-c-function' returns an unexpected value, 'some-function' will raise an
+'exn:fail' noting the actual return value and declaring it a bug. |#
+(define-syntax-rule (checked proc [expected consequence] ...)
+ (let-syntax-rule (cond-rhs result consequence-or-exception)
+ (if (eq? consequence-or-exception 'ok)
+ result
+ (raise consequence-or-exception))
+ (lambda args
+ (let ([result (apply proc args)])
+ (case result
+ [(expected) (cond-rhs result consequence)]
+ ...
+ [else (error (quote proc)
+ "unexpected return value ~v\n\
+This is a bug in ppamltracer! Report it to the maintainers."
+ result)])))))
+
+(define ((as-void proc) . args)
+ (void (apply proc args)))
+
+(define ppaml-tracer-init
+ (as-void
+ (checked ppaml_tracer_init
+ [0 'ok]
+ [1 (fail make-exn:fail:ppamltracer:otf:manager:initialization)]
+ [2 (fail make-exn:fail:ppamltracer:otf:writer:initialization)]
+ [3 (fail make-exn:fail:ppamltracer:otf:writer:resolution)]
+ [4 (fail make-exn:fail:ppamltracer:otf:writer:process-definition
+ "main")])))
+
+(define ppaml-tracer-done
+ (as-void
+ (checked ppaml_tracer_done
+ [0 'ok]
+ [1 (fail make-exn:fail:ppamltracer:otf:writer:close)])))
+
+(define ppaml-phase-init
+
+ (as-void
+ (checked ppaml_phase_init
+ [0 'ok]
+ [1 (fail make-exn:fail:ppamltracer:otf:writer:phase-definition)])))
+
+(define ppaml-phase-start
+ (as-void
+ (checked ppaml_phase_start
+ [0 'ok]
+ [1 (fail make-exn:fail:ppamltracer:timing:clock-acquisition)]
+ [2 (fail make-exn:fail:ppamltracer:otf:writer:entry)])))
+
+(define ppaml-phase-stop
+ (as-void
+ (checked ppaml_phase_stop
+ [0 'ok]
+ [1 (fail make-exn:fail:ppamltracer:timing:clock-acquisition)]
+ [2 (fail make-exn:fail:ppamltracer:otf:writer:exit)])))
+
+(define ppaml-phase-done
+ (as-void
+ (checked ppaml_phase_done
+ [0 'ok])))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; High-level API ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#| The functions in this section comprise a relatively safe API for this
+library--i.e., using them will help avoid resource leaks. Of course, Racket
+gives you plenty of rope to hang yourself--you could, for instance, call/cc
+your way back into the middle of some traced function. |#
+
+;; Predicates on '_tracer' and '_phase', to emulate declaration as structs.
+(define (cpointer-with-tag? obj tag)
+ (and (cpointer? obj)
+ (cpointer-has-tag? obj tag)))
+(define (tracer? obj) (cpointer-with-tag? obj 'ppaml_tracer_t))
+(define (phase? obj) (cpointer-with-tag? obj 'ppaml_phase_t))
+
+#| Execute a procedure in an exception-safe environment such that its resources
+are properly released upon exit. With the exception handling stripped away,
+
+ (managed-execution resource initialize initialize-args proc finalize)
+
+evaluates to
+
+ (begin (apply initialize (cons resource initialize-args))
+ (proc resource)
+ (finalize resource))
+|#
+(define (managed-execution resource initialize initialize-args proc finalize)
+ (apply initialize (cons resource initialize-args))
+ (let ([result
+ (with-handlers
+ ([exn? (lambda (exn)
+ #| An exception occurred during the execution of 'proc'.
+ Clean up and re-throw. |#
+ (with-handlers
+ ([exn? (lambda (exn)
+ #| An exception occurred during cleanup!
+ We're already responding to an existing
+ exception, though, so just ignore it. |#
+ (void))])
+ (finalize resource))
+ (raise exn))])
+ (proc resource))])
+ (finalize resource)
+ result))
+
+(define (call-with-tracer report-name-base proc)
+ (managed-execution (malloc-_tracer)
+ ppaml-tracer-init
+ (list report-name-base)
+ proc
+ ppaml-tracer-done))
+
+(define (call-with-phase tracer phase-name proc)
+ (managed-execution (malloc-_phase)
+ (lambda (phase tracer name)
+ ;; Reorder arguments to fit C API.
+ (ppaml-phase-init tracer phase name))
+ (list tracer phase-name)
+ proc
+ ppaml-phase-done))
+
+(define (call-with-phase-running phase proc)
+ (managed-execution phase
+ ppaml-phase-start
+ '()
+ (lambda (ignored) (proc))
+ ppaml-phase-stop))
+
+
+;;;;; Macro versions ;;;;;
+
+(define-syntax-rule (let/tracer [tracer report-name-base] body ...)
+ (call-with-tracer report-name-base (lambda (tracer) body ...)))
+
+(define-syntax-rule (let/phase tracer [phase phase-name] body ...)
+ (call-with-phase tracer phase-name (lambda (phase) body ...)))
+
+(define-syntax-rule (with-phase-running phase body ...)
+ (call-with-phase-running phase (lambda () body ...)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Module interface ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(provide
+ (contract-out [tracer? (-> any/c boolean?)]
+ [phase? (-> any/c boolean?)]
+ [call-with-tracer (parametric->/c [A]
+ (-> path-string? (-> tracer? A) A))]
+ [call-with-phase (parametric->/c [A]
+ (-> tracer? string? (-> phase? A) A))]
+ [call-with-phase-running (parametric->/c [A]
+ (-> phase? (-> A) A))])
+ let/tracer
+ let/phase
+ with-phase-running)
diff --git a/bindings/racket/manual.scrbl b/bindings/racket/manual.scrbl
new file mode 100644
index 0000000..f27731b
--- /dev/null
+++ b/bindings/racket/manual.scrbl
@@ -0,0 +1,181 @@
+#lang scribble/manual
+@;{ manual.scrbl -- Scribble documentation for ppamltracer-racket
+Copyright (C) 2013, 2014 Galois, Inc.
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+
+To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+Oregon, 97204-1622. }
+
+@(require (for-label racket/base
+ racket/sequence))
+@(require (for-label ppamltracer))
+
+@title{ppamltracer}
+
+ppamltracer is a lightweight, portable tracing library designed for explicit instrumention of generated code.
+If you're writing a compiler and need hard data on your optimizer's efficacy, ppamltracer is the library for you.
+This Racket library provides a high-level API on top of the libppamltracer C API.
+
+ppamltracer's usage can be summed up in a couple lines:
+
+@racketblock[
+(require ppamltracer)
+(let/tracer [tracer "/tmp/my_report"]
+ (let/phase tracer [phase "phase 1"]
+ (with-phase-running phase
+ (do-stuff)))
+ (let/phase tracer [phase "phase 2"]
+ (with-phase-running phase
+ (do-other-stuff))
+ (with-phase-running phase
+ (do-yet-more-stuff))))
+]
+
+This creates a report with the total runtime of @racket[do-stuff] recorded as "phase 1" and the total runtime of @racket[do-other-stuff] and @racket[do-yet-more-stuff] combined as "phase 2".
+
+@secref{getting-started} contains a more lengthy example.
+
+ppamltracer writes trace logs in the @hyperlink["http://tu-dresden.de/zih/otf/"]{Open Trace Format}, a free and open standard developed by the Zentrum für Informationsdienste und Hochleistungsrechnen (Center for Information Services and High-Performance Computing) at the Technical University of Dresden.
+
+We developed ppamltracer as part of DARPA's @hyperlink["http://darpa.mil/Our_Work/I2O/Programs/Probabilistic_Programming_for_Advanced_Machine_Learning_(PPAML).aspx"]{Probabilistic Programming for Advancing Machine Learning} (PPAML) project.
+
+
+@section[#:tag "getting-started"]{Getting Started}
+
+This basic example demonstrates using ppamltracer to trace two functions -- a factorial function and a Fibonacci number generator.
+
+@#reader scribble/comment-reader (racketblock
+;; simple.rkt -- basic ppamltracer example
+;; This file is in the public domain.
+
+(require racket/sequence)
+(require ppamltracer)
+
+(define (fact phase n)
+ ;; Record that we're running inside the factorial phase.
+ (with-phase-running phase
+ ;; Compute the factorial.
+ (if (= n 0)
+ 1
+ (* n (fact phase (- n 1))))))
+
+(define (fib phase n)
+ ;; Record that we're running inside the Fibonacci phase.
+ (with-phase-running phase
+ ;; Compute the nth Fibonacci number.
+ (case n
+ [(0 1) n]
+ [else (+ (fib phase (- n 1)) (fib phase (- n 2)))])))
+
+;; Start ppamltracer.
+(let/tracer [tracer "/tmp/simple_report"]
+ ;; Register the factorial phase.
+ (let/phase tracer [phase "fact"]
+ ;; Print factorials.
+ (printf "Factorials: ")
+ (sequence-for-each (lambda (n) (printf "~a " (fact phase n)))
+ (in-range 40))
+ (printf "\n"))
+ ;; Register the Fibonacci phase.
+ (let/phase tracer [phase "fib"]
+ ;; Print Fibonacci numbers.
+ (printf "Fibonacci numbers: ")
+ (sequence-for-each (lambda (n) (printf "~a " (fib phase n)))
+ (in-range 16))
+ (printf "\n")))
+)
+
+@section{API in Depth}
+
+@defmodule[ppamltracer]
+
+@subsection{Tracers}
+
+ppamltracer is fundamentally a set of stateful operations; the @racket[tracer] data type holds the state ppamltracer needs to operate properly.
+
+@defproc[(tracer? [obj any/c])
+ boolean?]{
+ Evaluates to @racket[#t] if and only if @racket[obj] is a @racket[tracer].
+}
+
+@defproc[(call-with-tracer [report-name-base path-string?]
+ [proc (-> tracer? A)])
+ A]{
+ Creates a new @racket[tracer].
+ The @racket[tracer] will save trace reports in Open Trace Format; all trace file paths will begin with @racket[report-name-base].
+}
+
+@defform[#:id let/tracer
+ #:literals (tracer)
+ (let/tracer [tracer report-name-base] body ...)
+ #:contracts ([report-name-base path-string?])]{
+ Macro version of @racket[call-with-tracer].
+ Equivalent to
+
+ @racketblock[
+ (call-with-tracer report-name-base (lambda (tracer) body ...))
+ ]
+}
+
+@subsection{Phases}
+
+A @racket[phase] represents a phase of execution about which the user wishes to gather timing statistics.
+
+@defproc[(phase? [obj any/c])
+ boolean?]{
+ Evaluates to @racket[#t] if and only if @racket[obj] is a @racket[phase].
+}
+
+@defproc[(call-with-phase [tracer tracer?]
+ [phase-name string?]
+ [proc (-> phase? A)])
+ A]{
+ Creates a new @racket[phase] attached to @racket[tracer] and named @racket[phase-name].
+}
+
+@defform[#:id let/phase
+ #:literals (phase)
+ (let/phase tracer [phase name] body ...)
+ #:contracts ([tracer tracer?]
+ [name string?])]{
+ Macro version of @racket[call-with-phase].
+ Equivalent to
+
+ @racketblock[
+ (call-with-phase tracer name (lambda (phase) body ...))
+ ]
+}
+
+@subsection{Tracing}
+
+@defproc[(call-with-phase-running [phase phase?]
+ [proc (-> A)])
+ A]{
+ Runs @racket[proc], associating information about its timing and execution with @racket[phase] in the trace report.
+ Should @racket[proc] throw an exception, @racket[call-with-phase-running] will stop tracing before propagating the exception up the stack.
+}
+
+@defform[#:id with-phase-running
+ #:literals (phase)
+ (with-phase-running phase body ...)
+ #:contracts ([phase phase?])]{
+ Macro version of @racket[call-with-phase-running].
+ Equivalent to
+
+ @racketblock[
+ (call-with-phase-running phase (lambda () body ...))
+ ]
+}
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..a5b80c6
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,64 @@
+# configure.ac -- autoconf script for ppamltracer
+# Copyright (C) 2013 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+# Fire up Autoconf.
+AC_PREREQ([2.69])
+AC_INIT([ppamltracer], [0.1.0], [bbarenblat@galois.com])
+
+# Fire up Automake. Use ustar format because we actually have file names
+# longer than 99 characters (hooray, Java).
+AM_INIT_AUTOMAKE([-Wall -Wno-gnu -Werror foreign tar-ustar no-dist-gzip \
+ dist-bzip2])
+AC_CONFIG_MACRO_DIR([m4])
+
+# Build quietly.
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+# Build a C library.
+AC_CONFIG_SRCDIR([config.h.in])
+AC_CONFIG_HEADERS([config.h])
+AC_PROG_CC
+AC_PROG_CC_C99
+# Automake 1.12 seems to require this, but automake 1.11 doesn't recognize it.
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+LT_INIT
+
+# Dependencies
+AC_CHECK_HEADERS([unistd.h])
+AC_CHECK_TYPE([clockid_t])
+GALOIS_PPAML_LIB_OPENTRACE(
+ [],
+ [AC_MSG_ERROR([both OTF development libraries and the 'otfconfig' program are required. You can install them from <http://tu-dresden.de/die_tu_dresden/zentrale_einrichtungen/zih/forschung/projekte/otf>.])])
+
+# Documentation
+DX_HTML_FEATURE(ON)
+DX_PDF_FEATURE(OFF)
+DX_PS_FEATURE(OFF)
+DX_INIT_DOXYGEN([ppamltracer], [Doxyfile], [doc])
+
+# Generate Makefiles and pkg-config file.
+AC_CONFIG_FILES([
+ Makefile
+ src/Makefile
+ include/Makefile])
+AC_CONFIG_FILES([ppamltracer.pc])
+
+# All done.
+AC_OUTPUT
diff --git a/examples/simple.c b/examples/simple.c
new file mode 100644
index 0000000..614205d
--- /dev/null
+++ b/examples/simple.c
@@ -0,0 +1,92 @@
+/* simple.c -- basic ppamltracer example
+ * This file is in the public domain.
+ *
+ * Compile this with
+ * cc -std=c99 -lppamltracer -o simple simple.c
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+
+#include <ppaml/tracer.h>
+
+// ppamltracer state
+ppaml_tracer_t tracer;
+ppaml_phase_t phase_fact;
+ppaml_phase_t phase_fib;
+
+
+// Prototypes
+unsigned long long fact(const unsigned short);
+unsigned long fib(const unsigned short);
+
+
+int main(int argc, char *argv[])
+{
+ /* Disable buffering on stdout so we can see the numbers as they are
+ * printed. */
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ // Start ppamltracer.
+ ppaml_tracer_init(&tracer, "/tmp/simple_report");
+
+ // Register the phases.
+ ppaml_phase_init(&tracer, &phase_fact, "fact");
+ ppaml_phase_init(&tracer, &phase_fib, "fib");
+
+ // Print factorials.
+ printf("Factorials: ");
+ for (unsigned short i = 0; i < 21; i++) {
+ printf("%lld ", fact(i));
+ }
+ printf("\n");
+
+ // Print Fibonacci numbers.
+ printf("Fibonacci numbers: ");
+ for (unsigned short i = 0; i < 28; i++) {
+ printf("%ld ", fib(i));
+ }
+ printf("\n");
+
+ // Finalize ppamltracer and exit.
+ ppaml_phase_done(&phase_fact);
+ ppaml_phase_done(&phase_fib);
+ ppaml_tracer_done(&tracer);
+ return 0;
+}
+
+unsigned long long fact(const unsigned short n)
+{
+ // Record that we have entered the 'fact' phase.
+ ppaml_phase_start(&phase_fact);
+
+ // Compute the factorial.
+ unsigned long long result;
+ if (n == 0) {
+ result = 1;
+ } else {
+ result = (unsigned long long)n * fact(n - 1);
+ }
+
+ // Record that we're exiting the 'fact' phase.
+ ppaml_phase_stop(&phase_fact);
+ return result;
+}
+
+unsigned long fib(const unsigned short n)
+{
+ // Record that we have entered the 'fib' phase.
+ ppaml_phase_start(&phase_fib);
+
+ // Compute the nth Fibonancci number.
+ unsigned long result;
+ if (n == 0 || n == 1) {
+ result = 1;
+ } else {
+ result = fib(n - 1) + fib(n - 2);
+ }
+
+ // Record that we're exiting the 'fact' phase.
+ ppaml_phase_stop(&phase_fib);
+ return result;
+}
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..5ef2a54
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,23 @@
+# Makefile.am -- automake script for ppamltracer
+# Copyright (C) 2013 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+nobase_include_HEADERS = \
+ ppaml/tracer.h \
+ ppaml/tracer/internal.h
diff --git a/include/ppaml/tracer.h b/include/ppaml/tracer.h
new file mode 100644
index 0000000..df9891a
--- /dev/null
+++ b/include/ppaml/tracer.h
@@ -0,0 +1,166 @@
+/* ppaml/tracer.h -- PPAML timing instrumentation interface
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+/**
+ * @file tracer.h
+ * Library interface.
+ *
+ * This file defines the top-level interface for ppamltracer.
+ *
+ * Since all the functions in this file operate on @ref ppaml_tracer_t and @ref
+ * ppaml_phase_t structs, their documentation has been moved to the relevant
+ * data structure pages.
+ */
+
+#ifndef PPAML_TRACER_H
+#define PPAML_TRACER_H
+
+#include "tracer/internal.h" // for ppaml_tracer_t and ppaml_phase_t
+
+/**
+ * @name Resource management
+ *
+ * @{
+ */
+
+/**
+ * Initializes a ppaml_tracer_t.
+ *
+ * @relates ppaml_tracer_t
+ *
+ * The trace report will be stored in Open Trace Format; all trace file paths
+ * will begin with @p report_name_base.
+ *
+ * @param[out] tracer pointer to the tracer to be initialized
+ * @param[in] report_name_base base file name for the report files
+ *
+ * @pre @p tracer is nonnull.
+ * @pre @p *tracer is uninitialized.
+ *
+ * @return 0 upon success
+ * @return 1 if the Open Trace Format file manager could not be initialized
+ * @return 2 if the Open Trace Format writer could not be initialized
+ * @return 3 if setting the trace resolution failed
+ * @return 4 if defining the main OTF process failed
+ *
+ * @post If the function return successfully, @p *tracer is initialized.
+ */
+int ppaml_tracer_init(ppaml_tracer_t *tracer, const char report_name_base[]);
+
+/**
+ * Finalizes a ppaml_tracer_t.
+ *
+ * @relates ppaml_tracer_t
+ *
+ * @param[out] tracer pointer to the tracer to be finalized
+ *
+ * @pre @p tracer is nonnull.
+ * @pre @p *tracer is initialized.
+ *
+ * @return 0 upon success
+ * @return 1 if the Open Trace Format writer could not be closed
+ *
+ * @post If the function return successfully, @p *tracer is uninitialized.
+ */
+int ppaml_tracer_done(ppaml_tracer_t *tracer);
+
+/**
+ * Initializes a ppaml_phase_t.
+ *
+ * @relates ppaml_phase_t
+ *
+ * @param[in] tracer pointer to the tracer which records this phase
+ * @param[out] phase pointer to the phase to be initialized
+ * @param[in] name name of the phase
+ *
+ * @pre @p tracer is nonnull.
+ * @pre @p *tracer is initialized.
+ * @pre @p phase is nonnull.
+ * @pre @p *phase is uninitialized.
+ *
+ * @return 0 upon success
+ * @return 1 if defining the phase failed
+ *
+ * @post If the function return successfully, @p *phase is initialized.
+ */
+int ppaml_phase_init(
+ ppaml_tracer_t *tracer,
+ ppaml_phase_t *phase,
+ const char name[]);
+
+/**
+ * Finalizes a ppaml_phase_t.
+ *
+ * @relates ppaml_phase_t
+ *
+ * @param[out] phase pointer to the phase to be finalized
+ *
+ * @pre @p phase is nonnull.
+ * @pre @p *phase is initialized.
+ *
+ * @return 0 upon success; a nonzero return indicates failure.
+ *
+ * @post If the function return successfully, @p *phase is uninitialized.
+ */
+int ppaml_phase_done(ppaml_phase_t *phase);
+
+/// @}
+
+/**
+ * @name Timing
+ *
+ * @{
+ */
+
+/**
+ * Records the start of a phase.
+ *
+ * @relates ppaml_phase_t
+ *
+ * @param[in] phase pointer to the phase
+ *
+ * @pre @p phase is nonnull.
+ * @pre @p *phase is initialized.
+ *
+ * @return 0 upon success
+ * @return 1 if getting the time failed
+ * @return 2 if recording the phase start failed
+ */
+int ppaml_phase_start(ppaml_phase_t *phase);
+
+/**
+ * Records the end of a phase.
+ *
+ * @relates ppaml_phase_t
+ *
+ * @param[in] phase pointer to the phase
+ *
+ * @pre @p phase is nonnull.
+ * @pre @p *phase is initialized.
+ *
+ * @return 0 upon success
+ * @return 1 if getting the time failed
+ * @return 2 if recording the phase stop failed
+ */
+int ppaml_phase_stop(ppaml_phase_t *phase);
+
+/// @}
+
+#endif
diff --git a/include/ppaml/tracer/internal.h b/include/ppaml/tracer/internal.h
new file mode 100644
index 0000000..217d7ad
--- /dev/null
+++ b/include/ppaml/tracer/internal.h
@@ -0,0 +1,111 @@
+/* ppaml/tracer/internal.h -- definitions of abstract types
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+/**
+ * @file internal.h
+ * Definitions of abstract types.
+ *
+ * @warning Do not include this file directly. Instead, include @ref
+ * ppaml/tracer.h.
+ *
+ * This file contains the implementations of abstract types which, for
+ * efficiency reasons, are exposed to the user.
+ */
+
+/* THIS FILE SHOULD NOT BE #INCLUDED DIRECTLY. Instead, #include
+ * <ppaml/tracer.h>. */
+
+#ifndef PPAML_TRACER_INTERNAL_H
+#define PPAML_TRACER_INTERNAL_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <otf.h>
+
+/**
+ * @struct ppaml_tracer_t ppaml/tracer/internal.h ppaml/tracer.h
+ * Tracer state bundle.
+ *
+ * ppamltracer is fundamentally a set of stateful operations; this struct holds
+ * the state ppamltracer needs to operate properly.
+ *
+ * To increase flexibility, ppamltracer users may allocate instances of this
+ * struct on the stack or heap.
+ *
+ * Newly-allocated instances of ppaml_tracer_t are invalid and must be
+ * initialized using @ref ppaml_tracer_init before they can be used. Once a
+ * ppaml_tracer_t is no longer required, it must be finalized using @ref
+ * ppaml_tracer_done.
+ */
+typedef struct {
+ /// @private The underlying Open Trace Format file manager.
+ OTF_FileManager *manager;
+ /// @private The underlying Open Trace Format output subsystem.
+ OTF_Writer *writer;
+} ppaml_tracer_t;
+
+/**
+ * `sizeof(`@ref ppaml_tracer_t`)`.
+ *
+ * @warning This constant is intended for interfacing with other languages. It
+ * is not part of the stable ppamltracer C API. Use
+ * `sizeof(`@ref ppaml_tracer_t`)` instead.
+ */
+const size_t ppaml_tracer_t_size;
+
+/**
+ * @struct ppaml_phase_t ppaml/tracer/internal.h ppaml/tracer.h
+ * A phase of execution to trace.
+ *
+ * A ppaml_phase_t represents a phase of execution about which the user wishes
+ * to gather timing statistics.
+ *
+ * To increase flexibility, ppamltracer users may allocate instances of this
+ * struct on the stack or heap.
+ *
+ * Newly-allocated instances of ppaml_phase_t are invalid and must be
+ * initialized using @ref ppaml_phase_init before they can be used. Once a
+ * ppaml_phase_t is no longer required, it must be finalized using @ref
+ * ppaml_phase_done.
+ */
+typedef struct {
+ /// @private The associated ppaml_tracer_t.
+ ppaml_tracer_t *tracer;
+ /**
+ * @private
+ * The Open Trace Format identifier for this phase.
+ *
+ * Phases are isomorphic to functions as understood by the Open Trace
+ * Format libraries; thus, this is a "function identifier".
+ */
+ uint32_t otf_function_id;
+} ppaml_phase_t;
+
+/**
+ * `sizeof(`@ref ppaml_phase_t`)`.
+ *
+ * @warning This constant is intended for interfacing with other languages. It
+ * is not part of the stable ppamltracer C API. Use
+ * `sizeof(`@ref ppaml_phase_t`)` instead.
+ */
+const size_t ppaml_phase_t_size;
+
+#endif
diff --git a/m4/ax_prog_doxygen.m4 b/m4/ax_prog_doxygen.m4
new file mode 100644
index 0000000..44b22b0
--- /dev/null
+++ b/m4/ax_prog_doxygen.m4
@@ -0,0 +1,532 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# DX_INIT_DOXYGEN(PROJECT-NAME, DOXYFILE-PATH, [OUTPUT-DIR])
+# DX_DOXYGEN_FEATURE(ON|OFF)
+# DX_DOT_FEATURE(ON|OFF)
+# DX_HTML_FEATURE(ON|OFF)
+# DX_CHM_FEATURE(ON|OFF)
+# DX_CHI_FEATURE(ON|OFF)
+# DX_MAN_FEATURE(ON|OFF)
+# DX_RTF_FEATURE(ON|OFF)
+# DX_XML_FEATURE(ON|OFF)
+# DX_PDF_FEATURE(ON|OFF)
+# DX_PS_FEATURE(ON|OFF)
+#
+# DESCRIPTION
+#
+# The DX_*_FEATURE macros control the default setting for the given
+# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
+# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
+# help (for MS users), 'CHI' for generating a seperate .chi file by the
+# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
+# output formats. The environment variable DOXYGEN_PAPER_SIZE may be
+# specified to override the default 'a4wide' paper size.
+#
+# By default, HTML, PDF and PS documentation is generated as this seems to
+# be the most popular and portable combination. MAN pages created by
+# Doxygen are usually problematic, though by picking an appropriate subset
+# and doing some massaging they might be better than nothing. CHM and RTF
+# are specific for MS (note that you can't generate both HTML and CHM at
+# the same time). The XML is rather useless unless you apply specialized
+# post-processing to it.
+#
+# The macros mainly control the default state of the feature. The use can
+# override the default by specifying --enable or --disable. The macros
+# ensure that contradictory flags are not given (e.g.,
+# --enable-doxygen-html and --enable-doxygen-chm,
+# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
+# feature will be automatically disabled (with a warning) if the required
+# programs are missing.
+#
+# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
+# with the following parameters: a one-word name for the project for use
+# as a filename base etc., an optional configuration file name (the
+# default is 'Doxyfile', the same as Doxygen's default), and an optional
+# output directory name (the default is 'doxygen-doc').
+#
+# Automake Support
+#
+# The following is a template aminclude.am file for use with Automake.
+# Make targets and variables values are controlled by the various
+# DX_COND_* conditionals set by autoconf.
+#
+# The provided targets are:
+#
+# doxygen-doc: Generate all doxygen documentation.
+#
+# doxygen-run: Run doxygen, which will generate some of the
+# documentation (HTML, CHM, CHI, MAN, RTF, XML)
+# but will not do the post processing required
+# for the rest of it (PS, PDF, and some MAN).
+#
+# doxygen-man: Rename some doxygen generated man pages.
+#
+# doxygen-ps: Generate doxygen PostScript documentation.
+#
+# doxygen-pdf: Generate doxygen PDF documentation.
+#
+# Note that by default these are not integrated into the automake targets.
+# If doxygen is used to generate man pages, you can achieve this
+# integration by setting man3_MANS to the list of man pages generated and
+# then adding the dependency:
+#
+# $(man3_MANS): doxygen-doc
+#
+# This will cause make to run doxygen and generate all the documentation.
+#
+# The following variable is intended for use in Makefile.am:
+#
+# DX_CLEANFILES = everything to clean.
+#
+# Then add this variable to MOSTLYCLEANFILES.
+#
+# ----- begin aminclude.am -------------------------------------
+#
+# ## --------------------------------- ##
+# ## Format-independent Doxygen rules. ##
+# ## --------------------------------- ##
+#
+# if DX_COND_doc
+#
+# ## ------------------------------- ##
+# ## Rules specific for HTML output. ##
+# ## ------------------------------- ##
+#
+# if DX_COND_html
+#
+# DX_CLEAN_HTML = @DX_DOCDIR@/html
+#
+# endif DX_COND_html
+#
+# ## ------------------------------ ##
+# ## Rules specific for CHM output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_chm
+#
+# DX_CLEAN_CHM = @DX_DOCDIR@/chm
+#
+# if DX_COND_chi
+#
+# DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
+#
+# endif DX_COND_chi
+#
+# endif DX_COND_chm
+#
+# ## ------------------------------ ##
+# ## Rules specific for MAN output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_man
+#
+# DX_CLEAN_MAN = @DX_DOCDIR@/man
+#
+# endif DX_COND_man
+#
+# ## ------------------------------ ##
+# ## Rules specific for RTF output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_rtf
+#
+# DX_CLEAN_RTF = @DX_DOCDIR@/rtf
+#
+# endif DX_COND_rtf
+#
+# ## ------------------------------ ##
+# ## Rules specific for XML output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_xml
+#
+# DX_CLEAN_XML = @DX_DOCDIR@/xml
+#
+# endif DX_COND_xml
+#
+# ## ----------------------------- ##
+# ## Rules specific for PS output. ##
+# ## ----------------------------- ##
+#
+# if DX_COND_ps
+#
+# DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
+#
+# DX_PS_GOAL = doxygen-ps
+#
+# doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
+#
+# @DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
+# cd @DX_DOCDIR@/latex; \
+# rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+# $(DX_LATEX) refman.tex; \
+# $(MAKEINDEX_PATH) refman.idx; \
+# $(DX_LATEX) refman.tex; \
+# countdown=5; \
+# while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+# refman.log > /dev/null 2>&1 \
+# && test $$countdown -gt 0; do \
+# $(DX_LATEX) refman.tex; \
+# countdown=`expr $$countdown - 1`; \
+# done; \
+# $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
+#
+# endif DX_COND_ps
+#
+# ## ------------------------------ ##
+# ## Rules specific for PDF output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_pdf
+#
+# DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
+#
+# DX_PDF_GOAL = doxygen-pdf
+#
+# doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
+#
+# @DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
+# cd @DX_DOCDIR@/latex; \
+# rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+# $(DX_PDFLATEX) refman.tex; \
+# $(DX_MAKEINDEX) refman.idx; \
+# $(DX_PDFLATEX) refman.tex; \
+# countdown=5; \
+# while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+# refman.log > /dev/null 2>&1 \
+# && test $$countdown -gt 0; do \
+# $(DX_PDFLATEX) refman.tex; \
+# countdown=`expr $$countdown - 1`; \
+# done; \
+# mv refman.pdf ../@PACKAGE@.pdf
+#
+# endif DX_COND_pdf
+#
+# ## ------------------------------------------------- ##
+# ## Rules specific for LaTeX (shared for PS and PDF). ##
+# ## ------------------------------------------------- ##
+#
+# if DX_COND_latex
+#
+# DX_CLEAN_LATEX = @DX_DOCDIR@/latex
+#
+# endif DX_COND_latex
+#
+# .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
+#
+# .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+#
+# doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
+#
+# doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+#
+# @DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
+# rm -rf @DX_DOCDIR@
+# $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
+#
+# DX_CLEANFILES = \
+# @DX_DOCDIR@/@PACKAGE@.tag \
+# -r \
+# $(DX_CLEAN_HTML) \
+# $(DX_CLEAN_CHM) \
+# $(DX_CLEAN_CHI) \
+# $(DX_CLEAN_MAN) \
+# $(DX_CLEAN_RTF) \
+# $(DX_CLEAN_XML) \
+# $(DX_CLEAN_PS) \
+# $(DX_CLEAN_PDF) \
+# $(DX_CLEAN_LATEX)
+#
+# endif DX_COND_doc
+#
+# ----- end aminclude.am ---------------------------------------
+#
+# LICENSE
+#
+# Copyright (c) 2009 Oren Ben-Kiki <oren@ben-kiki.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 12
+
+## ----------##
+## Defaults. ##
+## ----------##
+
+DX_ENV=""
+AC_DEFUN([DX_FEATURE_doc], ON)
+AC_DEFUN([DX_FEATURE_dot], OFF)
+AC_DEFUN([DX_FEATURE_man], OFF)
+AC_DEFUN([DX_FEATURE_html], ON)
+AC_DEFUN([DX_FEATURE_chm], OFF)
+AC_DEFUN([DX_FEATURE_chi], OFF)
+AC_DEFUN([DX_FEATURE_rtf], OFF)
+AC_DEFUN([DX_FEATURE_xml], OFF)
+AC_DEFUN([DX_FEATURE_pdf], ON)
+AC_DEFUN([DX_FEATURE_ps], ON)
+
+## --------------- ##
+## Private macros. ##
+## --------------- ##
+
+# DX_ENV_APPEND(VARIABLE, VALUE)
+# ------------------------------
+# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
+AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
+
+# DX_DIRNAME_EXPR
+# ---------------
+# Expand into a shell expression prints the directory part of a path.
+AC_DEFUN([DX_DIRNAME_EXPR],
+ [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
+
+# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
+# -------------------------------------
+# Expands according to the M4 (static) status of the feature.
+AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
+
+# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
+# ----------------------------------
+# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
+AC_DEFUN([DX_REQUIRE_PROG], [
+AC_PATH_TOOL([$1], [$2])
+if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
+ AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
+ AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+fi
+])
+
+# DX_TEST_FEATURE(FEATURE)
+# ------------------------
+# Expand to a shell expression testing whether the feature is active.
+AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
+
+# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
+# -------------------------------------------------
+# Verify that a required features has the right state before trying to turn on
+# the DX_CURRENT_FEATURE.
+AC_DEFUN([DX_CHECK_DEPEND], [
+test "$DX_FLAG_$1" = "$2" \
+|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
+ requires, contradicts) doxygen-DX_CURRENT_FEATURE])
+])
+
+# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
+# ----------------------------------------------------------
+# Turn off the DX_CURRENT_FEATURE if the required feature is off.
+AC_DEFUN([DX_CLEAR_DEPEND], [
+test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+])
+
+# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
+# CHECK_DEPEND, CLEAR_DEPEND,
+# REQUIRE, DO-IF-ON, DO-IF-OFF)
+# --------------------------------------------
+# Parse the command-line option controlling a feature. CHECK_DEPEND is called
+# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
+# otherwise CLEAR_DEPEND is called to turn off the default state if a required
+# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
+# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
+# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
+AC_DEFUN([DX_ARG_ABLE], [
+ AC_DEFUN([DX_CURRENT_FEATURE], [$1])
+ AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
+ AC_ARG_ENABLE(doxygen-$1,
+ [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
+ [--enable-doxygen-$1]),
+ DX_IF_FEATURE([$1], [don't $2], [$2]))],
+ [
+case "$enableval" in
+#(
+y|Y|yes|Yes|YES)
+ AC_SUBST([DX_FLAG_$1], 1)
+ $3
+;; #(
+n|N|no|No|NO)
+ AC_SUBST([DX_FLAG_$1], 0)
+;; #(
+*)
+ AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
+;;
+esac
+], [
+AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
+$4
+])
+if DX_TEST_FEATURE([$1]); then
+ $5
+ :
+fi
+AM_CONDITIONAL(DX_COND_$1, DX_TEST_FEATURE([$1]))
+if DX_TEST_FEATURE([$1]); then
+ $6
+ :
+else
+ $7
+ :
+fi
+])
+
+## -------------- ##
+## Public macros. ##
+## -------------- ##
+
+# DX_XXX_FEATURE(DEFAULT_STATE)
+# -----------------------------
+AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
+AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
+AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
+AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
+AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
+AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
+AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
+AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
+
+# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
+# ---------------------------------------------------------
+# PROJECT also serves as the base name for the documentation files.
+# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
+AC_DEFUN([DX_INIT_DOXYGEN], [
+
+# Files:
+AC_SUBST([DX_PROJECT], [$1])
+AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
+AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
+
+# Environment variables used inside doxygen.cfg:
+DX_ENV_APPEND(SRCDIR, $srcdir)
+DX_ENV_APPEND(PROJECT, $DX_PROJECT)
+DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
+DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
+
+# Doxygen itself:
+DX_ARG_ABLE(doc, [generate any doxygen documentation],
+ [],
+ [],
+ [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
+ DX_REQUIRE_PROG([DX_PERL], perl)],
+ [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
+
+# Dot for graphics:
+DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_DOT], dot)],
+ [DX_ENV_APPEND(HAVE_DOT, YES)
+ DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
+ [DX_ENV_APPEND(HAVE_DOT, NO)])
+
+# Man pages generation:
+DX_ARG_ABLE(man, [generate doxygen manual pages],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_MAN, YES)],
+ [DX_ENV_APPEND(GENERATE_MAN, NO)])
+
+# RTF file generation:
+DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_RTF, YES)],
+ [DX_ENV_APPEND(GENERATE_RTF, NO)])
+
+# XML file generation:
+DX_ARG_ABLE(xml, [generate doxygen XML documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_XML, YES)],
+ [DX_ENV_APPEND(GENERATE_XML, NO)])
+
+# (Compressed) HTML help generation:
+DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_HHC], hhc)],
+ [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
+ DX_ENV_APPEND(GENERATE_HTML, YES)
+ DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
+ [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
+
+# Seperate CHI file generation.
+DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
+ [DX_CHECK_DEPEND(chm, 1)],
+ [DX_CLEAR_DEPEND(chm, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_CHI, YES)],
+ [DX_ENV_APPEND(GENERATE_CHI, NO)])
+
+# Plain HTML pages generation:
+DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
+ [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
+ [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
+ [],
+ [DX_ENV_APPEND(GENERATE_HTML, YES)],
+ [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
+
+# PostScript file generation:
+DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_LATEX], latex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_DVIPS], dvips)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# PDF file generation:
+DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# LaTeX generation for PS and/or PDF:
+AM_CONDITIONAL(DX_COND_latex, DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf))
+if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
+ DX_ENV_APPEND(GENERATE_LATEX, YES)
+else
+ DX_ENV_APPEND(GENERATE_LATEX, NO)
+fi
+
+# Paper size for PS and/or PDF:
+AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
+ [a4wide (default), a4, letter, legal or executive])
+case "$DOXYGEN_PAPER_SIZE" in
+#(
+"")
+ AC_SUBST(DOXYGEN_PAPER_SIZE, "")
+;; #(
+a4wide|a4|letter|legal|executive)
+ DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
+;; #(
+*)
+ AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
+;;
+esac
+
+#For debugging:
+#echo DX_FLAG_doc=$DX_FLAG_doc
+#echo DX_FLAG_dot=$DX_FLAG_dot
+#echo DX_FLAG_man=$DX_FLAG_man
+#echo DX_FLAG_html=$DX_FLAG_html
+#echo DX_FLAG_chm=$DX_FLAG_chm
+#echo DX_FLAG_chi=$DX_FLAG_chi
+#echo DX_FLAG_rtf=$DX_FLAG_rtf
+#echo DX_FLAG_xml=$DX_FLAG_xml
+#echo DX_FLAG_pdf=$DX_FLAG_pdf
+#echo DX_FLAG_ps=$DX_FLAG_ps
+#echo DX_ENV=$DX_ENV
+])
diff --git a/m4/otf.m4 b/m4/otf.m4
new file mode 100644
index 0000000..42b0224
--- /dev/null
+++ b/m4/otf.m4
@@ -0,0 +1,74 @@
+# otf.m4 -- helper function to detect OTF libraries -*- Autoconf -*-
+# Copyright (C) 2013 Galois, Inc.
+#
+# This library is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This library is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this library. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+# GALOIS_PPAML_LIB_OPENTRACE(ACTION-IF-FOUND, ACTION-IF-NOT-FOUND)
+# This macro expands the OTF_CFLAGS and OTF_LIBS variables, but it does not add
+# them to CFLAGS or LIBS.
+AC_DEFUN([GALOIS_PPAML_LIB_OPENTRACE], [
+ AC_REQUIRE([AC_PROG_SED])
+ otf_ok=whoKnows
+ # Check for otfconfig.
+ AC_PATH_PROG([OTFCONFIG], [otfconfig])
+ AC_ARG_VAR([OTFCONFIG], [path to otfconfig binary])
+ if test -z "$OTFCONFIG"; then
+ otf_ok=no
+ else
+ OTF_CFLAGS="`"$OTFCONFIG" --includes`"
+ OTF_LIBS="`"$OTFCONFIG" --libs`"
+ # Save CFLAGS and LIBS, and reset CFLAGS and LIBS to the OTF
+ # requirements.
+ SAVECFLAGS="$CFLAGS"
+ SAVELIBS="$LIBS"
+ CFLAGS="$OTF_CFLAGS"
+ LIBS="$OTF_LIBS"
+ # Try to compile using the CFLAGS.
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <otf.h>"],
+ [int x = otf_errno;])],
+ [otf_compile_headers=yes],
+ [otf_compile_headers=no])
+ # Try to compile using the libraries.
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <otf.h>"],
+ [int x = otf_errno;])],
+ [otf_link=yes],
+ [otf_link=no])
+ # Did we pass?
+ if test \( "$otf_compile_headers" = "yes" \) -a \
+ \( "$otf_link" = "yes" \); then
+ otf_ok=yes
+ else
+ otf_ok=no
+ fi
+ # Restore CFLAGS and LIBS.
+ CFLAGS="$SAVECFLAGS"
+ LIBS="$SAVELIBS"
+ fi
+ # Execute the users' blocks.
+ if test "$otf_ok" = "yes"; then
+ AC_SUBST([OTF_CFLAGS])
+ AC_SUBST([OTF_LIBS])
+ ifelse([$1], , :, [$1])
+ else
+ ifelse([$2], , :, [$2])
+ fi
+])
diff --git a/ppamltracer.pc.in b/ppamltracer.pc.in
new file mode 100644
index 0000000..a2a9a5f
--- /dev/null
+++ b/ppamltracer.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ppamltracer
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lppamltracer
+Libs.private: @OTF_LIBS@
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..d5f4ab2
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,35 @@
+# Makefile.am -- automake script for ppamltracer
+# Copyright (C) 2013 Galois, Inc.
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
+# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
+# Oregon, 97204-1622.
+
+lib_LTLIBRARIES = libppamltracer.la
+libppamltracer_la_SOURCES = \
+ $(srcdir)/require.h \
+ $(srcdir)/timing.c \
+ $(srcdir)/timing.h \
+ $(srcdir)/tracer.c
+libppamltracer_la_CFLAGS = \
+ -I$(top_srcdir)/include \
+ -std=c99 \
+ -Wall \
+ -Wextra \
+ -pedantic \
+ @OTF_CFLAGS@
+libppamltracer_la_LIBADD = @OTF_LIBS@
+libppamltracer_la_LDFLAGS = -export-symbols-regex '^ppaml_'
diff --git a/src/index.dox b/src/index.dox
new file mode 100644
index 0000000..3dd4b77
--- /dev/null
+++ b/src/index.dox
@@ -0,0 +1,45 @@
+/* index.dox -- front-page documentation for ppamltracer -*- c -*-
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+/**
+ * @mainpage Overview
+ *
+ * ppamltracer is a lightweight, portable tracing library designed for explicit
+ * instrumention of generated code. If you're writing a compiler and need hard
+ * data on your optimizer's efficacy, ppamltracer is the library for you.
+ *
+ * @ref simple.c shows ppamltracer in action tracing two phases of computation
+ * (factorials and Fibonacci numbers), and honestly, it's probably all the API
+ * documentation you need. You can also have a look at @ref ppaml_tracer_t and
+ * @ref ppaml_phase_t, the data structures which ppamltracer manipulates.
+ *
+ * ppamltracer writes trace logs in the [Open Trace Format]
+ * (http://tu-dresden.de/zih/otf/), a free and open standard developed by the
+ * Zentrum f&uuml;r Informationsdienste und Hochleistungsrechnen (Center for
+ * Information Services and High-Performance Computing) at the Technical
+ * University of Dresden.
+ *
+ * We developed ppamltracer as part of DARPA's [Probabilistic Programming for
+ * Advancing Machine Learning]
+ * (http://darpa.mil/Our_Work/I2O/Programs/Probabilistic_Programming_for_Advanced_Machine_Learning_(PPAML%29.aspx)
+ * (PPAML) project.
+ *
+ * @example simple.c
+ */
diff --git a/src/require.h b/src/require.h
new file mode 100644
index 0000000..f731c15
--- /dev/null
+++ b/src/require.h
@@ -0,0 +1,46 @@
+/* require.h -- useful error-handling macros
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#ifndef REQUIRE_H
+#define REQUIRE_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define require_not(var, val, ret_val) \
+ do { \
+ if ((var) != val) { \
+ r = ret_val; \
+ goto done; \
+ } \
+ } while (0)
+#define require_zero(var, ret_val) require_not(var, 0, ret_val)
+#define require_one(var, ret_val) require_not(var, 1, ret_val)
+
+#define require_nonnull(ptr, ret_val) \
+ do { \
+ if ((ptr) == NULL) { \
+ r = ret_val; \
+ goto done; \
+ } \
+ } while (0)
+
+#endif
diff --git a/src/timing.c b/src/timing.c
new file mode 100644
index 0000000..25cbba7
--- /dev/null
+++ b/src/timing.c
@@ -0,0 +1,86 @@
+/* timing.c -- cross-platform wall time
+ * Copyright (C) 2013 Galois, Inc. All rights reserved. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#define _POSIX_C_SOURCE 199309L
+
+#include <stdint.h>
+
+#include "timing.h"
+#include "require.h"
+
+#define ignore(var) ((void)(var))
+
+const uint64_t MICRO_PER_BASE = 1000000;
+const uint64_t NANO_PER_MICRO = 1000;
+
+// Try to use the POSIX timers, if possible.
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#if (HAVE_UNISTD_H && _POSIX_TIMERS > 0)
+
+# include <time.h>
+
+# if __linux__
+ /* Hopefully, you're running linux >=2.6.28, and
+ * CLOCK_MONOTONIC_RAW exists. */
+ static const clockid_t CLOCK_ID = CLOCK_MONOTONIC_RAW;
+# elif _POSIX_MONOTONIC_CLOCK
+ // You're not on Linux, but you've got a POSIX monotonic clock.
+ static const clockid_t CLOCK_ID = CLOCK_MONOTONIC;
+# else
+ // Just use the POSIX wall clock.
+ static const clockid_t CLOCK_ID = CLOCK_REALTIME;
+# endif
+
+ int timing_get_wall(uint64_t *const result)
+ {
+ int r = 0;
+ struct timespec now;
+ require_zero(clock_gettime(CLOCK_ID, &now), 1);
+ *result = (uint64_t)now.tv_sec * MICRO_PER_BASE
+ + (uint64_t)now.tv_nsec / NANO_PER_MICRO;
+ done: return r;
+ }
+
+#elif (__APPLE__ && __MACH__)
+
+ /* No POSIX timers, but we're on a Mac, so we can use
+ * 'mach_absolute_time'. */
+# include <mach/mach_time.h>
+
+ int timing_get_wall(uint64_t *const result)
+ {
+ static mach_timebase_info_data_t timebase_info;
+ int r = 0;
+ *result = mach_absolute_time();
+ /* *result is now in units of Mach ticks. Convert that to
+ * nanoseconds using the timebase information that Mach
+ * provides. Note that 'timebase_info' is static, so it got
+ * zeroed out at the start of the program run; if its
+ * denominator is still zero, we've definitely not stored
+ * anything in it yet. */
+ if (timebase_info.denom == 0) {
+ require_zero(mach_timebase_info(&timebase_info), 1);
+ }
+ *result = *result * timebase_info.numer / timebase_info.denom;
+ // Convert nanoseconds to microseconds.
+ *result /= NANO_PER_MICRO;
+ done: return r;
+ }
+
+#else
+
+ // I have no clue what wacky platform you're on.
+# error Unsupported timing platform
+
+ int timing_get_wall(uint64_t *const result)
+ {
+ ignore(result);
+ return -1;
+ }
+
+#endif
diff --git a/src/timing.h b/src/timing.h
new file mode 100644
index 0000000..167e536
--- /dev/null
+++ b/src/timing.h
@@ -0,0 +1,32 @@
+/* timing.h -- cross-platform wall time
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#ifndef TIMING_H
+#define TIMING_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+
+int timing_get_wall(uint64_t *result);
+
+#endif
diff --git a/src/tracer.c b/src/tracer.c
new file mode 100644
index 0000000..be2f3cc
--- /dev/null
+++ b/src/tracer.c
@@ -0,0 +1,133 @@
+/* tracer.c -- PPAML timing instrumentation
+ * Copyright (C) 2013 Galois, Inc.
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * To contact Galois, complete the Web form at
+ * <http://corp.galois.com/contact/> or write to Galois, Inc., 421 Southwest
+ * 6th Avenue, Suite 300, Portland, Oregon, 97204-1622. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <otf.h>
+
+#include <ppaml/tracer.h>
+#include <ppaml/tracer/internal.h>
+
+#include "timing.h"
+#include "require.h"
+
+const size_t ppaml_tracer_t_size = sizeof(ppaml_tracer_t);
+const size_t ppaml_phase_t_size = sizeof(ppaml_phase_t);
+
+int ppaml_tracer_init(
+ ppaml_tracer_t *const tracer,
+ const char report_name_base[])
+{
+ int r = 0;
+ // Initialize the file manager.
+ const uint32_t max_fds = 1024; // TODO: ulimit default on my system
+ tracer->manager = OTF_FileManager_open(max_fds);
+ require_nonnull(tracer->manager, 1);
+ // Initialize the writer.
+ tracer->writer = OTF_Writer_open(report_name_base, 1, tracer->manager);
+ require_nonnull(tracer->writer, 2);
+ // Record that we have a resolution of 1 microsecond.
+ require_one(
+ OTF_Writer_writeDefTimerResolution(tracer->writer, 0, 1000000),
+ 3);
+ // Define an OTF process (i.e., a thread).
+ require_one(
+ OTF_Writer_writeDefProcess(tracer->writer, 0, 1, "main", 0),
+ 4);
+done: return r;
+}
+
+int ppaml_tracer_done(ppaml_tracer_t *const tracer)
+{
+ int r = 0;
+ // Close the writer.
+ require_one(OTF_Writer_close(tracer->writer), 1);
+ tracer->writer = NULL;
+ // Close the file manager.
+ OTF_FileManager_close(tracer->manager);
+ tracer->manager = NULL;
+done: return r;
+}
+
+int ppaml_phase_init(
+ ppaml_tracer_t *const tracer,
+ ppaml_phase_t *const phase,
+ const char name[])
+{
+ static uint32_t next_function_id = 1;
+ int r = 0;
+ require_one(
+ OTF_Writer_writeDefFunction(
+ tracer->writer,
+ 0, // stream id = 1
+ next_function_id,
+ name,
+ 0, // no function group
+ 0), // no source code
+ 1);
+ phase->tracer = tracer;
+ phase->otf_function_id = next_function_id;
+ next_function_id++;
+done: return r;
+}
+
+int ppaml_phase_done(ppaml_phase_t *const phase)
+{
+ phase->tracer = NULL;
+ phase->otf_function_id = 0;
+ return 0;
+}
+
+int ppaml_phase_start(ppaml_phase_t *const phase)
+{
+ int r = 0;
+ uint64_t now;
+ require_zero(timing_get_wall(&now), 1);
+ require_one(
+ OTF_Writer_writeEnter(
+ phase->tracer->writer,
+ now,
+ phase->otf_function_id,
+ 1, // process id = 1
+ 0), // no source code
+ 2);
+done: return r;
+}
+
+int ppaml_phase_stop(ppaml_phase_t *const phase)
+{
+ int r = 0;
+ uint64_t now;
+ require_zero(timing_get_wall(&now), 1);
+ require_one(
+ OTF_Writer_writeLeave(
+ phase->tracer->writer,
+ now,
+ phase->otf_function_id,
+ 1, // process id = 1
+ 0), // no source code
+ 2);
+done: return r;
+}